题目传送门

Description

给定 $ n, k $,请求出长度为 $ n $ 的逆序对数恰好为 $ k $ 的排列的个数。答案对 $ 10 ^ 9 + 7 $ 取模。

对于一个长度为 $ n $ 的排列 $ p $,其逆序对数即满足 $ i < j $ 且 $ p_i > p_j $ 的二元组 $ (i, j) $ 的数量。

一行两个整数 $ n, k $。

一行,表示答案。

对于 $ 20% $ 的数据,$ n, k \leq 20 $;

对于 $ 40% $ 的数据,$ n, k \leq 100 $;

对于 $ 60% $ 的数据,$ n, k \leq 5000 $;

对于 $ 100% $ 的数据,$ 1 \leq n, k \leq 100000, 1 \leq k \leq \binom{n}{2} $。

Solution

可以想到,对于一个排列 \(p\) ,假设 \(s_i\) 表示以 \(i\) 为右端点的逆序对个数,那么可以看出一个 \(s_{1,2,...,n}\) 对应一个唯一的 \(p\) ,而一个 \(s_{1,2,...,n}\) 合法当且仅当 \(\forall i,s_i\le i-1\)。

可以想到我们可以容斥,即枚举哪些点 \(s_i\) 越界了。那么,我们也就只需要求出

\[\prod_{i=1}^{n}(1-x^i)
\]

的前面 \(k\) 项。

这个时候我们就有两种办法,一种是用多项式,取 \(\ln\) ,然后用 \(\ln(1-x)=\sum_{j=1}^{\infty} -\frac{x^j}{j}\) \(\Theta(k\log k)\) 直接多项式 \(\ln,\exp\) 算出来,考场上我就写的这个,不过原题要写任意模数 NTT,估计不是很好写,而且常数很大,可以拿头过。

还有另外一种 \(\Theta(k\sqrt k)\) 做法。你发现选出一个 \(\{1,2,...,n\}\) 的集合还有另外一种选法,即假设你现在有一个递减序列,你每次有两种选择:

  1. 整体加 \(1\)

  2. 整体加 \(1\) 并在后面增加一个 \(1\)

那么,我们就可以进行 dp 了,因为考虑到我们最多使用 \(\sqrt k\) 次操作 \(2\),所以,我们可以设 \(f_{i,j}\) 表示在经过 \(i\) 此操作 \(2\) 后数字总和为 \(j\) 的方案数。

可以得到转移式:

\[f_{i,j}=f_{i,j-i}+f_{i-1,j-i}-f_{i-1,j-n-1}
\]

Code

#include <bits/stdc++.h>
using namespace std; #define Int register int
#define mod 1000000007
#define MAXN 200005 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);} int n,k,upp = 2e5,fac[MAXN],ifac[MAXN],f[505][MAXN];
int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
int qkpow (int a,int b){
int res = 1;for (;b;b >>= 1,a = mul (a,a)) if (b & 1) res = mul (res,a);
return res;
}
void Sub (int &a,int b){a = dec (a,b);}
void Add (int &a,int b){a = add (a,b);}
int binom (int a,int b){return a >= b ? mul (fac[a],mul (ifac[b],ifac[a - b])) : 0;} int F[MAXN]; signed main(){
read (n,k);int up = 500;
fac[0] = 1;for (Int i = 1;i <= upp;++ i) fac[i] = mul (fac[i - 1],i);
ifac[upp] = qkpow (fac[upp],mod - 2);for (Int i = upp;i;-- i) ifac[i - 1] = mul (ifac[i],i);
f[0][0] = 1;
for (Int i = 1;i <= up;++ i)
for (Int j = 0;j <= k;++ j){
if (j >= i) Add (f[i][j],add (f[i][j - i],f[i - 1][j - i]));
if (j >= n + 1) Sub (f[i][j],f[i - 1][j - n - 1]);
}
for (Int S = 0;S <= k;++ S)
for (Int i = 0;i <= up;++ i)
if (i & 1) Sub (F[S],f[i][S]);
else Add (F[S],f[i][S]);
int ans = 0;
for (Int S = 0;S <= k;++ S) Add (ans,mul (F[S],binom (k - S + n - 1,n - 1)));
write (ans),putchar ('\n');
return 0;
}

题解 「2017 山东一轮集训 Day7」逆序对的更多相关文章

  1. 【LOJ6077】「2017 山东一轮集训 Day7」逆序对 生成函数+组合数+DP

    [LOJ6077]「2017 山东一轮集训 Day7」逆序对 题目描述 给定 n,k ,请求出长度为 n的逆序对数恰好为 k 的排列的个数.答案对 109+7 取模. 对于一个长度为 n 的排列 p ...

  2. loj #6077. 「2017 山东一轮集训 Day7」逆序对

    #6077. 「2017 山东一轮集训 Day7」逆序对   题目描述 给定 n,k n, kn,k,请求出长度为 n nn 的逆序对数恰好为 k kk 的排列的个数.答案对 109+7 10 ^ 9 ...

  3. 「2017 山东一轮集训 Day7」逆序对

    题解: 满满的套路题.. 首先显然从大到小枚举 然后每次生成的逆序对是1----(i-1)的 这样做dp是nk的 复杂度太高了 那我们转化一下问题 变成sigma(ai   (ai<i)  )= ...

  4. LOJ6077「2017 山东一轮集训 Day7」逆序对 (生成函数+多项式exp?朴素DP!)

    题面 给定 n , k n,k n,k ,求长度为 n n n 逆序对个数为 k k k 的排列个数,对 1 e 9 + 7 \rm1e9+7 1e9+7 取模. 1 ≤ n , k ≤ 100   ...

  5. loj6077. 「2017 山东一轮集训 Day7」逆序对

    题目描述: loj 题解: 容斥+生成函数. 考虑加入的第$i$个元素对结果的贡献是$[0,i-1]$,我们可以列出生成函数. 长这样:$(1)*(1+x)*(1+x+x^2)*--*(1+x+x^2 ...

  6. LOJ #6119. 「2017 山东二轮集训 Day7」国王

    Description 在某个神奇的大陆上,有一个国家,这片大陆的所有城市间的道路网可以看做是一棵树,每个城市要么是工业城市,要么是农业城市,这个国家的人认为一条路径是 exciting 的,当且仅当 ...

  7. loj6119 「2017 山东二轮集训 Day7」国王

    题目描述 在某个神奇的大陆上,有一个国家,这片大陆的所有城市间的道路网可以看做是一棵树,每个城市要么是工业城市,要么是农业城市,这个国家的人认为一条路径是 exciting 的,当且仅当这条路径上的工 ...

  8. loj #6079. 「2017 山东一轮集训 Day7」养猫【最大费用最大流】

    首先假设全睡觉,然后用费用流考虑平衡要求建立网络流 把1~n的点看作是i-k+1~k这一段的和,连接(i,i+k,1,e[i]-s[i]),表示把i改成吃饭,能对i~i+k-1这一段的点产生影响:然后 ...

  9. LOJ6079「2017 山东一轮集训 Day7」养猫

    养ImmortalCO k可重区间问题 的增强版:有上下界! 直接都选择s[i],然后再把一些调整到e[i] 考虑通过最大流的“最大”,使得至少每k个有me个e, 通过最大流的“上界”,限制每k个最多 ...

随机推荐

  1. Go版本依赖--伪版本

    目录 1.简介 2. 什么是伪版本 3. 伪版本风格 4. 如何获取伪版本 1.简介 在go.mod中通常使用语义化版本来标记依赖,比如v1.2.3.v0.1.5等.因为go.mod文件通常是go命令 ...

  2. docker-compose权限不够

    root@kali:~# docker-compose version -bash: /usr/local/bin/docker-compose: 权限不够 chmod +x /usr/local/b ...

  3. SpringBoot应用中使用AOP记录接口访问日志

    SpringBoot应用中使用AOP记录接口访问日志 本文主要讲述AOP在mall项目中的应用,通过在controller层建一个切面来实现接口访问的统一日志记录. AOP AOP为Aspect Or ...

  4. EternalBlue永恒之蓝渗透测试

    Eternal Blue(永恒之蓝)-ms17-010渗透测试 第一次做的渗透测试,也是第一次去写博客,还望各位师傅多多指正 :) 工具 1.靶机系统 window7 开放445以及139端口 2.k ...

  5. 痞子衡嵌入式:MCUXpresso Config Tools初体验(Pins, Clocks, Peripherals)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso Config Tools三大件(Pins, Clocks, Peripherals). 不知道大家有没有这样的感受 ...

  6. Linux与Windows文件同步

    Linux与Windows文件同步 本次采用的同步方式是rsync,Rsync是一款免费且强大的同步软件,可以镜像保存整个目录树和文件系统,同时保持原来文件的权限.时间.软硬链接.第一次同步时会复制全 ...

  7. Python之pyyaml模块

    pyyaml模块在python中用于处理yaml格式数据,主要使用yaml.safe_dump().yaml.safe_load()函数将python值和yaml格式数据相互转换.当然也存在yaml. ...

  8. vue 双向绑定(v-model 双向绑定、.sync 双向绑定、.sync 传对象)

    1. v-model实现自定义组件双向绑定 v-model其实是个语法糖,如果没按照相应的规范定义组件,直接写v-model是不会生效的.再说一遍,类似于v-on:click可以简写成@click,v ...

  9. Linux下cat命令的使用

    1.普通用法-->查看文件内容 cat file_name 查看文件时的相关参数: 1.cat f1.txt,查看f1.txt文件的内容. 2.cat -n f1.txt,查看f1.txt文件的 ...

  10. 安装或更新时,pip出错,“No module named ‘pip’”

    解决办法: 在pycharm终端(Terminal)中 首先执行 :python -m ensurepip 然后执行 :python -m pip install --upgrade pip