题面

给定

n

,

k

n,k

n,k ,求长度为

n

n

n 逆序对个数为

k

k

k 的排列个数,对

1

e

9

+

7

\rm1e9+7

1e9+7 取模。

1

n

,

k

100

000

1\leq n,k\leq 100\,000

1≤n,k≤100000 。

题解

首先,不要看到逆序对就手忙脚乱,它其实是可控的。

d

i

d_i

di​ 为第

i

i

i 个数前面比它大的数的个数,满足条件

d

i

[

0

,

i

)

d_i\in[0,i)

di​∈[0,i) 。一个

d

d

d 序列,实际上只需要满足这个条件,他就能够成立,并且唯一对应一个排列。这个在POJ3761 Bubble Sort中证明过,可以通过

d

d

d 序列构造出排列来。

然后,就是个比较经典的问题:

n

n

n 个非负整数,各有上限,求总和为

k

k

k 的方案数。这题的特殊之处在于,每个数的上界依次是

0

0

0 到

n

1

n-1

n−1 。

先设

f

(

x

)

f(x)

f(x) 为这

n

n

n 个非负整数没有上限的情况下,总和为

x

x

x 的方案数。经验告诉我们,利用隔板法,可得

f

(

x

)

=

C

(

x

+

n

1

,

x

)

f(x)=C(x+n-1,x)

f(x)=C(x+n−1,x) 。

生成函数

我们可以用生成函数来做,走起!

可以得到第

i

i

i 个数的生成函数为

1

+

x

+

x

2

+

.

.

.

+

x

i

1

=

(

j

=

0

x

j

)

(

j

=

i

x

j

)

=

1

x

i

x

1

1+x+x^2+...+x^{i-1}=(\sum_{j=0}^{\infty}x^j)-(\sum_{j=i}^{\infty}x^j)=\frac{1-x^i}{x-1}

1+x+x2+...+xi−1=(j=0∑∞​xj)−(j=i∑∞​xj)=x−11−xi​

(我们用

[

[

x

i

]

]

F

(

x

)

[[x^i]]F(x)

[[xi]]F(x) 来表示函数

F

(

x

)

F(x)

F(x) 的

i

i

i 次项系数)于是答案可表示为

[

[

x

k

]

]

i

=

1

n

1

x

i

x

1

=

[

[

x

k

]

]

(

(

1

x

1

)

n

i

=

0

n

(

1

x

i

)

)

=

[

[

x

k

]

]

(

(

i

=

0

x

i

)

n

i

=

0

n

(

1

x

i

)

)

=

j

=

0

k

[

[

x

j

]

]

(

i

=

0

x

i

)

n

[

[

x

k

j

]

]

(

i

=

0

n

(

1

x

i

)

)

[[x^k]]\prod_{i=1}^{n}\frac{1-x^i}{x-1}=[[x^k]]\Big((\frac{1}{x-1})^n\prod_{i=0}^{n}(1-x^i)\Big)\\ =[[x^k]]\Big((\sum_{i=0}^{\infty}x^i)^n\prod_{i=0}^n(1-x^i)\Big)\\ =\sum_{j=0}^{k}[[x^j]](\sum_{i=0}^{\infty}x^i)^n\cdot[[x^{k-j}]]\Big(\prod_{i=0}^n(1-x^i)\Big)

[[xk]]i=1∏n​x−11−xi​=[[xk]]((x−11​)ni=0∏n​(1−xi))=[[xk]]((i=0∑∞​xi)ni=0∏n​(1−xi))=j=0∑k​[[xj]](i=0∑∞​xi)n⋅[[xk−j]](i=0∏n​(1−xi))

这个东西:

[

[

x

j

]

]

(

i

=

0

x

i

)

n

[[x^j]](\sum_{i=0}^{\infty}x^i)^n

[[xj]](∑i=0∞​xi)n ,不就是无限制的

n

n

n 个自然数的情况吗?不就是

f

(

j

)

f(j)

f(j) ?

=

j

=

0

k

f

(

j

)

[

[

x

k

j

]

]

(

i

=

0

n

(

1

x

i

)

)

=\sum_{j=0}^{k}f(j)\cdot[[x^{k-j}]]\Big(\prod_{i=0}^n(1-x^i)\Big)

=j=0∑k​f(j)⋅[[xk−j]](i=0∏n​(1−xi))

接下来,我们要对这个函数

i

=

0

n

(

1

x

i

)

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

∏i=0n​(1−xi) 开膛破肚了。

先取对数转化成加法:

exp

(

i

=

0

n

ln

(

1

x

i

)

)

\exp\Big( \sum_{i=0}^n\ln(1-x^i) \Big)

exp(i=0∑n​ln(1−xi))

然后,我们手推二项式

ln

\ln

ln ,运用链式法则求导再求积分:

exp

(

i

=

0

n

ln

(

1

x

i

)

)

=

exp

(

i

=

0

n

(

ln

(

1

x

i

)

(

1

x

i

)

)

d

x

)

=

exp

(

i

=

0

n

i

x

i

1

1

x

i

d

x

)

\exp\Big( \sum_{i=0}^n\ln(1-x^i) \Big)=\exp\Big( \sum_{i=0}^n\int(\ln'(1-x^i)\cdot(1-x^i)'){\rm dx} \Big)\\ =\exp\Big( \sum_{i=0}^n\int\frac{-ix^{i-1}}{1-x^i}{\rm dx} \Big)

exp(i=0∑n​ln(1−xi))=exp(i=0∑n​∫(ln′(1−xi)⋅(1−xi)′)dx)=exp(i=0∑n​∫1−xi−ixi−1​dx)

再手推

g

(

x

)

=

1

x

i

g(x)=1-x^i

g(x)=1−xi 取模

x

k

+

1

x^{k+1}

xk+1 下的逆元。不难发现

(

1

x

i

)

(

1

+

x

i

+

x

2

i

+

x

3

i

+

.

.

.

)

=

1

x

i

+

x

i

x

2

i

+

x

2

i

.

.

.

1

(1-x^i)(1+x^i+x^{2i}+x^{3i}+...)=1-x^i+x^i-x^{2i}+x^{2i}-...\equiv1

(1−xi)(1+xi+x2i+x3i+...)=1−xi+xi−x2i+x2i−...≡1 ,因此它的逆元是

h

(

x

)

=

1

+

x

i

+

x

2

i

+

x

3

i

+

.

.

.

h(x)=1+x^i+x^{2i}+x^{3i}+...

h(x)=1+xi+x2i+x3i+... 。代入进去:

exp

(

i

=

0

n

i

x

i

1

1

x

i

d

x

)

=

exp

(

i

=

0

n

i

x

i

1

(

j

=

0

x

i

j

)

d

x

)

=

exp

(

i

=

0

n

(

j

=

1

i

x

i

j

1

)

d

x

)

=

exp

(

i

=

0

n

(

j

=

1

i

x

i

j

i

j

)

)

=

exp

(

i

=

1

k

(

j

i

n

j

)

x

i

)

\exp\Big( \sum_{i=0}^n\int\frac{-ix^{i-1}}{1-x^i}{\rm dx} \Big)=\exp\Big( \sum_{i=0}^n\int-ix^{i-1}(\sum_{j=0}^{\infty}x^{ij}){\rm dx} \Big)\\ =\exp\Big( \sum_{i=0}^n\int(\sum_{j=1}^{\infty}-ix^{ij-1}){\rm dx} \Big)\\ =\exp\Big( \sum_{i=0}^n(\sum_{j=1}^{\infty}-i\frac{x^{ij}}{ij}) \Big)\\ =\exp\Big( \sum_{i=1}^{k} -(\sum_{j|i}^nj)x^i \Big)

exp(i=0∑n​∫1−xi−ixi−1​dx)=exp(i=0∑n​∫−ixi−1(j=0∑∞​xij)dx)=exp(i=0∑n​∫(j=1∑∞​−ixij−1)dx)=exp(i=0∑n​(j=1∑∞​−iijxij​))=exp(i=1∑k​−(j∣i∑n​j)xi)

中间的

j

i

n

j

\sum_{j|i}^nj

∑j∣in​j 其实就是

i

i

i 小于等于

n

n

n 的因数和,可以用埃筛预处理出来。然后再用多项式exp就可以求出这个多项式了,令该多项式的

i

i

i 次项系数为

G

[

i

]

G[i]

G[i] ,那么答案就是

j

=

0

k

C

(

j

+

n

1

,

j

)

G

[

k

j

]

\sum_{j=0}^{k}C(j+n-1,j)\cdot G[k-j]

j=0∑k​C(j+n−1,j)⋅G[k−j]

预处理阶乘求组合数就完了。时间复杂度

O

(

n

log

n

)

O(n\log n)

O(nlogn) 。还得写任意模数NTT之类。

动态规划

但是多项式exp的常数有好几十,其实不优,很难跑过 1s。

我们其实可以用容斥,枚举超过上限的个数,答案转化过来,其实也是上面的一个式子:

j

=

0

k

f

(

j

)

[

[

x

k

j

]

]

(

i

=

0

n

(

1

x

i

)

)

\sum_{j=0}^{k}f(j)\cdot[[x^{k-j}]]\Big(\prod_{i=0}^n(1-x^i)\Big)

j=0∑k​f(j)⋅[[xk−j]](i=0∏n​(1−xi))

不熟悉生成函数的可能有点晕,但是熟知

D

P

\rm DP

DP 的我们应该可以意识到,右边的

[

[

x

k

j

]

]

(

i

=

0

n

(

1

x

i

)

)

[[x^{k-j}]]\Big(\prod_{i=0}^n(1-x^i)\Big)

[[xk−j]](∏i=0n​(1−xi)) 其实是个

0

/

1

0/1

0/1 背包问题!每个物品的大小依次是

1

1

1 到

n

n

n ,要么不取,要么取,取的话贡献的权值不是

1

1

1 而是

1

-1

−1,背包记录的是所有方案物品权值积的和。也可以说,绝对值是放物品方案数,符号是

1

-1

−1 的物品个数次方。

这个就很让人头疼。我们知道背包问题是根硬骨头,铁打的

O

(

n

m

)

O(nm)

O(nm) ,经常让人绝望。但是也不乏一些特殊情况的优化,比如用随机排序解决总和为

0

0

0 的背包最值问题(缩小背包大小),再比如这道题。这道题的特殊之处就在于每个物品的大小分别是

1

1

1 到

n

n

n 。

这样我们可以发现一个结论:物品个数不超过

k

\sqrt k

k

​ 的级别!因为考虑最坏情况,只需要

1

1

1~

k

\sqrt k

k

​ 放进去,总大小就足以达到

k

k

k 左右。

所以,设

d

p

[

i

]

[

j

]

dp[i][j]

dp[i][j] 为放

i

i

i 个数进去,总和为

j

j

j 的方案数,那么总状态数大约是

k

k

k\sqrt k

kk

​ ,可以存得下。再借鉴LOJ#6089 小 Y 的背包计数问题的思路,我们可以进行

O

(

1

)

O(1)

O(1) 转移:

  • 把已有的

    i

    i

    i 个数每个加一,可得转移:

    d

    p

    [

    i

    ]

    [

    j

    i

    ]

    d

    p

    [

    i

    ]

    [

    j

    ]

    dp[i][j-i]\rightarrow dp[i][j]

    dp[i][j−i]→dp[i][j] 。

  • 把已有的数每个加一,再往里边放一个 1,可得转移

    d

    p

    [

    i

    1

    ]

    [

    j

    i

    ]

    d

    p

    [

    i

    ]

    [

    j

    ]

    dp[i-1][j-i]\rightarrow dp[i][j]

    dp[i−1][j−i]→dp[i][j] 。

  • 上述两种转移算进来了不合法情况,即最大的数是一个

    n

    +

    1

    n+1

    n+1 ,因此我们把这些情况去除掉。去掉最大的

    n

    +

    1

    n+1

    n+1 后,方案数等于

    d

    p

    [

    i

    1

    ]

    [

    j

    n

    1

    ]

    dp[i-1][j-n-1]

    dp[i−1][j−n−1] ,因此可得转移

    (

    d

    p

    [

    i

    1

    ]

    [

    j

    n

    1

    ]

    )

    d

    p

    [

    i

    ]

    [

    j

    ]

    (-dp[i-1][j-n-1])\rightarrow dp[i][j]

    (−dp[i−1][j−n−1])→dp[i][j] 。

时间复杂度

O

(

k

k

)

O(k\sqrt k)

O(kk

​) ,比多项式exp快得多。

CODE

动规做法

  1. #include<set>
  2. #include<map>
  3. #include<stack>
  4. #include<cmath>
  5. #include<ctime>
  6. #include<queue>
  7. #include<bitset>
  8. #include<cstdio>
  9. #include<cstring>
  10. #include<iostream>
  11. #include<algorithm>
  12. using namespace std;
  13. #define MAXN 100005
  14. #define LL long long
  15. #define DB double
  16. #define ENDL putchar('\n')
  17. #define lowbit(x) (-(x) & (x))
  18. #define FI first
  19. #define SE second
  20. #define SI(x) set<x>::iterator
  21. #define BI bitset<63>
  22. #define eps (1e-9)
  23. #define SQ (450)
  24. LL read() {
  25. LL f=1,x=0;char s = getchar();
  26. while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
  27. while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
  28. return f*x;
  29. }
  30. void putpos(LL x) {
  31. if(!x) return ;
  32. putpos(x/10); putchar('0'+(x%10));
  33. }
  34. void putnum(LL x) {
  35. if(!x) putchar('0');
  36. else if(x < 0) putchar('-'),putpos(-x);
  37. else putpos(x);
  38. }
  39. const int MOD = 1000000007;
  40. int n,m,s,o,k;
  41. int fac[MAXN<<2],inv[MAXN<<2],invf[MAXN<<2];
  42. int C(int n,int m) {
  43. if(m < 0 || m > n) return 0;
  44. return fac[n] *1ll* invf[n-m] % MOD *1ll* invf[m] % MOD;
  45. }
  46. int dp[SQ][MAXN];
  47. int dpp[MAXN];
  48. int main() {
  49. n = read();k = read();
  50. int sq = 1;
  51. while((sq+1)*1ll*(sq+2)/2ll <= k) sq ++;
  52. fac[0]=fac[1]=inv[0]=inv[1]=invf[0]=invf[1]=1;
  53. for(int i = 2;i <= 200000;i ++) {
  54. fac[i] = fac[i-1]*1ll*i % MOD;
  55. inv[i] = (MOD-inv[MOD%i]) *1ll* (MOD/i) % MOD;
  56. invf[i] = invf[i-1] *1ll* inv[i] % MOD;
  57. }
  58. dp[0][0] = 1;
  59. dpp[0] = 1;
  60. for(int i = 1;i <= sq;i ++) {
  61. for(int j = (i+1)*i/2;j <= k;j ++) {
  62. dp[i][j] = (dp[i][j-i] + dp[i-1][j-i]) % MOD;
  63. if(j > n) (dp[i][j] += MOD-dp[i-1][j-n-1]) %= MOD;
  64. (dpp[j] += ((i&1) ? (MOD-1):1)*1ll*dp[i][j] % MOD) %= MOD;
  65. }
  66. }
  67. int ans = 0;
  68. for(int i = 0;i <= k;i ++) {
  69. (ans += C(i+n-1,i) *1ll* dpp[k-i] % MOD) %= MOD;
  70. }
  71. printf("%d\n",ans);
  72. return 0;
  73. }

LOJ6077「2017 山东一轮集训 Day7」逆序对 (生成函数+多项式exp?朴素DP!)的更多相关文章

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

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

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

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

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

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

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

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

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

    题目传送门 Description 给定 $ n, k $,请求出长度为 $ n $ 的逆序对数恰好为 $ k $ 的排列的个数.答案对 $ 10 ^ 9 + 7 $ 取模. 对于一个长度为 $ n ...

  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. 【Java面试】请简单说一下你对受检异常和非受检异常的理解

    Hi,我是Mic 今天给大家分享一道阿里一面的面试题. 这道题目比较基础,但是确难倒了很多人. 关于"受检异常和非受检异常的理解" 我们来看看普通人和高手的回答. 普通人: 嗯.. ...

  2. node线上项目连接mysql出现 504 Gateway Time-Out

    var connection = mysql.createConnection({host : 'localhost',user : 'root',password : '123456',port: ...

  3. Spring Data JPA系列3:JPA项目中核心场景与进阶用法介绍

    大家好,又见面了. 到这里呢,已经是本SpringData JPA系列文档的第三篇了,先来回顾下前面两篇: 在第1篇<Spring Data JPA系列1:JDBC.ORM.JPA.Spring ...

  4. Linux文本三剑客-grep

    Global search REgular expression and Print out the line 全局搜索正则表达式并打印行 作用: 对标准输入的行进行分析,过滤指定的行. 模式: 格式 ...

  5. 简单性能测试:springboot-2.x vs actix-web-4.x benchmark

    性能测试:springboot-2.x vs actix-web-4.x benchmark 转载请注明出处 https://www.cnblogs.com/funnyzpc/p/15956465.h ...

  6. SuperSocket 1.6 创建一个简易的报文长度在头部的Socket服务器

    我们来做一个头为6位报文总长度,并且长度不包含长度域自身的例子.比如这样的Socket报文000006123456. 添加SuperSocket.Engine,直接使用Nuget搜索SuperSock ...

  7. STM32与物联网01-ESP8266基本操作

    ESP8266物联网简介 ESP8266简介 ESP8266 是上海乐鑫公司开发的一款具有 WiFi 功能的控制芯片,它带有完整的 TCP/IP 协议栈,因此可以用作物联网开发. ESP8266 本身 ...

  8. java getway springcloud 记录请求数据

    java getway springcloud 记录请求数据,兼容post请求无参数和response返回无参数 方式1 import com.icar.web.icarutils.util.Clie ...

  9. 5-9 Leaf 分布式ID

    Leaf 什么Leaf leaf是叶子的意思 我们使用的Leaf是美团公司开源的一个分布式序列号(id)生成系统 我们可以在Github网站上下载项目直接使用 为什么需要Leaf 上面的图片中 是一个 ...

  10. day03_1_idea教程

    # idea使用教程 # 一.idea相关概念介绍 ## 1.1 IDE概念介绍 集成开发环境(IDE,Integrated Development Environment)是用于提供程序开发环境的应 ...