题面

给定

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

动规做法

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<ctime>
#include<queue>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 100005
#define LL long long
#define DB double
#define ENDL putchar('\n')
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define SI(x) set<x>::iterator
#define BI bitset<63>
#define eps (1e-9)
#define SQ (450)
LL read() {
LL f=1,x=0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f*x;
}
void putpos(LL x) {
if(!x) return ;
putpos(x/10); putchar('0'+(x%10));
}
void putnum(LL x) {
if(!x) putchar('0');
else if(x < 0) putchar('-'),putpos(-x);
else putpos(x);
}
const int MOD = 1000000007;
int n,m,s,o,k;
int fac[MAXN<<2],inv[MAXN<<2],invf[MAXN<<2];
int C(int n,int m) {
if(m < 0 || m > n) return 0;
return fac[n] *1ll* invf[n-m] % MOD *1ll* invf[m] % MOD;
}
int dp[SQ][MAXN];
int dpp[MAXN];
int main() {
n = read();k = read();
int sq = 1;
while((sq+1)*1ll*(sq+2)/2ll <= k) sq ++;
fac[0]=fac[1]=inv[0]=inv[1]=invf[0]=invf[1]=1;
for(int i = 2;i <= 200000;i ++) {
fac[i] = fac[i-1]*1ll*i % MOD;
inv[i] = (MOD-inv[MOD%i]) *1ll* (MOD/i) % MOD;
invf[i] = invf[i-1] *1ll* inv[i] % MOD;
}
dp[0][0] = 1;
dpp[0] = 1;
for(int i = 1;i <= sq;i ++) {
for(int j = (i+1)*i/2;j <= k;j ++) {
dp[i][j] = (dp[i][j-i] + dp[i-1][j-i]) % MOD;
if(j > n) (dp[i][j] += MOD-dp[i-1][j-n-1]) %= MOD;
(dpp[j] += ((i&1) ? (MOD-1):1)*1ll*dp[i][j] % MOD) %= MOD;
}
}
int ans = 0;
for(int i = 0;i <= k;i ++) {
(ans += C(i+n-1,i) *1ll* dpp[k-i] % MOD) %= MOD;
}
printf("%d\n",ans);
return 0;
}

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. conda和pip加速参考

    conda install和创建虚拟环境下载慢,可以修改/root/.condarc文件: vim /root/.condarc 各系统都可以通过修改用户目录下的 .condarc 文件.Window ...

  2. GDKOI 2021 Day3 PJ 懵逼记

    今天早了一点起来,初三的大奆都来做比赛了, 自然,自测的有许多 AK 虽然今天的题比昨天简单,但还是脑子还是十分迟钝,以至于贪心都想不出 真为明天的提高组而担忧 T1 斜率被卡 90 ,直接用勾股定理 ...

  3. 28.MysQL的日志管理及备份与恢复

    MySQL 索引.事务与存储引擎 目录 MySQL 索引.事务与存储引擎 MySQL 索引 索引的概念 索引的作用及副作用 索引的作用 索引的副作用 创建索引的原则依据 索引的分类和创建 普通索引 唯 ...

  4. RPA-UiPath视频教程1

    UiPath下载.安装.激活.第一个案例Helloworld!.参数类型.变量的介绍和使用 https://www.bilibili.com/video/av92816532 RPA直播公开课2020 ...

  5. Python爬虫+数据可视化教学:分析猫咪交易数据

    猫猫这么可爱 不会有人不喜欢吧: 猫猫真的很可爱,和我女朋友一样可爱~你们可以和女朋友一起养一只可爱猫猫女朋友都有的吧?啊没有的话当我没说-咳咳网上的数据太多.太杂,而且我也不知道哪个网站的数据比较好 ...

  6. 如何查看/修改Redis密码

    一.修改密码: 打开redis.windows.conf文件,默认是没有红框框里这句话的,因为默认密码是"",就是没有,跟MySql一样. 加上这句话意思就是密码修改为 root ...

  7. Django定时任务Django-crontab的使用

    在使用的django做测试平台时,,多多少少都会遇到需要定时任务的功能,比如定时执行任务,检查订单之类 的.可能是一段时间,比如每隔 10分钟执行一次,也可能是定点时间,比如 14:00 执行,也可能 ...

  8. 使用Win自带的远程工具连接Linux

    网上教程一大堆,我这边只简单记录一下,主要是黑屏问题,和剪贴板问题.Win连接Linux,一般都是使用的xrdp, 如果是使用的旧版本的Ubuntu,建议先装一下xfce桌面,gnome桌面一般连不起 ...

  9. python sock5代理

    安装 pysocks:pip install pysocks # coding:utf-8 ''' @version: python3.6 @author: 'eric' @license: Apac ...

  10. Qt点名器

    项目已开源,点击跳转 废话不多说,直接上代码. CMakeLists.txt cmake_minimum_required(VERSION 3.10) project(qt-caller) find_ ...