题目传送门

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. ES6扩展——正则扩展(u、y修饰符)

    //下面三行代码效果一样 //全局匹配开头为a的 const regexp1 = /^a/g; const regexp2 = new RegExp('a','g'); const regexp3 = ...

  2. 移动端 uni-app 滑动事件 精确判断手指滑动方向

    移动端根据手指滑动操作判断滑动方向 设计思路: 1.根据移动端touchstart和touchend方法获取手指触摸屏幕的开始坐标和结束坐标 2.根据两个坐标计算与水平方向的夹角 3.根据夹角判断当前 ...

  3. 一种封装Retrofit的方法,可以自动解析Gson,回避Method return type must not include a type variable or wildcard: retrofit2.Call<T>的问题

    封装目的:屏蔽底层实现,提供统一接口,并支持Gson自动转化 最初封装: //请求方法 interface RequestListener { interface PostListener { @PO ...

  4. 分布式ID生成器及redis,etcd分布式锁

    分布式id生成器 有时我们需要能够生成类似MySQL自增ID这样不断增大,同时又不会重复的id.以支持业务中的高并发场景.比较典型的,电商促销时,短时间内会有大量的订单涌入到系统,比如每秒10w+.明 ...

  5. 剑指 Offer 34. 二叉树中和为某一值的路径

    剑指 Offer 34. 二叉树中和为某一值的路径 输入一棵二叉树和一个整数,打印出二叉树中节点值的和为输入整数的所有路径.从树的根节点开始往下一直到叶节点所经过的节点形成一条路径. 示例: 给定如下 ...

  6. 20210826 Lighthouse,Miner,Lyk Love painting,Revive

    考场 T1 这不裸的容斥 T2 这不裸的欧拉路,先从奇数度点开始走,走不了就传送 T3 什么玩意,暴力都不会 T4 点分树??? 仔细想了一波,发现 T1 T2 都好做,T3 二分答案后可以暴力贪心, ...

  7. 20210803 noip29

    考场 第一次在 hz 考试.害怕会困,但其实还好 看完题感觉不太难,估计有人 AK. T3 比较套路,没办法枚举黑点就从 LCA 处考虑,在一个点变成黑点时计算其他点和它的 LCA 的贡献,暴力跳父亲 ...

  8. 各色Tarjan集合

    #include<bits/stdc++.h> using namespace std; const int N=100000,M=200000; //所有Tarjan都要: // dfn ...

  9. Mysql常用sql语句(10)- is null 空值查询

    测试必备的Mysql常用sql语句系列 https://www.cnblogs.com/poloyy/category/1683347.html 前言 is null是一个关键字来的,用于判断字段的值 ...

  10. C# List集合类常用操作 (一)

    所有操作基于以下类 class Employees { public int Id { get; set; } public string Name { get; set; } public stri ...