题目大意:

  求满足比之前的任何数小的有A个,比之后的任何数小的有B个的长度为n的排列个数。

题目分析:

  首先写出递推式,设s(n,k)表示长度为n的排列,比之前的数小的数有k个。

  我们假设新加入的数为1,那么s(n,k)=s(n-1,k-1)+(n-1)*s(n,k)。

  这个式子是第一类斯特林数的递推式。

  用h(n,a,b)表示满足题目给出条件的排列个数。

  得出h(n,a,b)=Σs(k,a-1)*s(n-k-1,b-1)*C(n-1,k)。直观的理解就是将原排列从最高点分成两部分,两部分分别组合然后乘起来。

  这样我们发现h(n,a,b)=s(n-1,a+b-2)*C(a+b-2,a-1)。这实际上就是给出一个a+b-2的排列,然后选出其中需要的点放到右边,我们不用考虑多余的点,因为它们的排列已经被计算。

  由于无符号第一类斯特林数对应着升幂的系数,构造x(x+1)(x+2)...(x+n-1),它的x^k的系数等于s(n,k)的值,由于最高项系数为1,所以分治FFT。

代码:

  

 #include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std; const int mod = ;
const int gg = ; int n,a,b; vector<int> res[]; int up[]; int ord[]; int fast_pow(int now,int pw){
if(pw == ) return ;
if(pw == ) return now;
int z = fast_pow(now,pw/);
z = (1ll*z*z)%mod;
if(pw & ){z= (1ll*z*now)%mod;}
return z;
} void fft(int now,int len,int f){
for(int i=;i<len;i++) if(i<ord[i]) swap(res[now][i],res[now][ord[i]]);
for(int i=;i<len;i<<=){
int wn = fast_pow(gg,(mod-)/(i<<));
if(f == -) wn = fast_pow(wn,mod-);
for(int j=;j<len;j+=(i<<)){
for(int k=,w=;k<i;k++,w = (1ll*w*wn)%mod){
int x = res[now][j+k],y = (1ll*w*res[now][j+k+i])%mod;
res[now][j+k] = (x+y)%mod;
res[now][j+k+i] = (x-y+mod)%mod;
}
}
}
if(f == -){
int iv = fast_pow(len,mod-);
for(int i=;i<len;i++) res[now][i] = (1ll*res[now][i]*iv)%mod;
}
} void multi(int p1,int p2){
int n1 = res[p1].size()-,n2 = res[p2].size()-;
int len = ,om = ;
while(len <= (n1+n2+))len<<=,om++;
for(int i=n1+;i<len;i++) res[p1].push_back();
for(int i=n2+;i<len;i++) res[p2].push_back();
for(int i=;i<len;i++) ord[i] = (ord[i>>]>>)+((i&)<<om-);
fft(p1,len,);fft(p2,len,);
for(int i=;i<len;i++){
res[p1][i] = (1ll*res[p1][i]*res[p2][i])%mod;
if(res[p1][i] < ) res[p1][i]+=mod;
}
fft(p1,len,-);
res[p2].clear();
} void divide(int l,int r,int now){
if(l == r) {up[now] = l;return;}
int mid = (l+r)/;
divide(l,mid,now<<);
divide(mid+,r,now<<|);
multi(up[now<<],up[now<<|]);
up[now] = up[now<<];
} void work(){
if(a == || b == ){puts("");return;}
if(n == ){if(a+b==)puts(""); else puts(""); return;}
int c = ;
if(a<b) swap(a,b);
if(a- > a+b-) c = ;
for(int i=;i<=a-;i++){
c = (1ll*c*(a+b--i))%mod;
c = (1ll*c*fast_pow(i,mod-))%mod;
}
for(int i=;i<n;i++) res[i].push_back(i-),res[i].push_back();
divide(,n-,);
c = (1ll*c*res[up[]][a+b-])%mod;
printf("%d",c);
} int main(){
scanf("%d%d%d",&n,&a,&b);
work();
return ;
}

Codeforces960G Bandit Blues 【斯特林数】【FFT】的更多相关文章

  1. 【CF960G】Bandit Blues(第一类斯特林数,FFT)

    [CF960G]Bandit Blues(第一类斯特林数,FFT) 题面 洛谷 CF 求前缀最大值有\(a\)个,后缀最大值有\(b\)个的长度为\(n\)的排列个数. 题解 完完全全就是[FJOI] ...

  2. codeforces960G. Bandit Blues

    题目链接:codeforces960G 来看看三倍经验:hdu4372 luogu4609 某蒟蒻的关于第一类斯特林数的一点理解QAQ:https://www.cnblogs.com/zhou2003 ...

  3. 【xsy1301】 原题的价值 组合数+斯特林数+FFT

    题目大意:求$n\times2^{\frac{(n-1)(n-2)/2}{2}}\sum\limits_{i=0}^{n-1}\dbinom{n-1}{i}i^k$ 数据范围:$n≤10^9$,$k≤ ...

  4. CF960G Bandit Blues 第一类斯特林数+分治+FFT

    题目传送门 https://codeforces.com/contest/960/problem/G 题解 首先整个排列的最大值一定是 \(A\) 个前缀最大值的最后一个,也是 \(B\) 个后缀最大 ...

  5. CF960G Bandit Blues 【第一类斯特林数 + 分治NTT】

    题目链接 CF960G 题解 同FJOI2016只不过数据范围变大了 考虑如何预处理第一类斯特林数 性质 \[x^{\overline{n}} = \sum\limits_{i = 0}^{n}\be ...

  6. CF960G Bandit Blues(第一类斯特林数)

    传送门 可以去看看litble巨巨关于第一类斯特林数的总结 设\(f(i,j)\)为\(i\)个数的排列中有\(j\)个数是前缀最大数的方案数,枚举最小的数的位置,则有递推式\(f(i,j)=f(i- ...

  7. CF960G Bandit Blues 第一类斯特林数、NTT、分治/倍增

    传送门 弱化版:FJOI2016 建筑师 由上面一题得到我们需要求的是\(\begin{bmatrix} N - 1 \\ A + B - 2 \end{bmatrix} \times \binom ...

  8. CF960G Bandit Blues 分治+NTT(第一类斯特林数)

    $ \color{#0066ff}{ 题目描述 }$ 给你三个正整数 \(n\),\(a\),\(b\),定义 \(A\) 为一个排列中是前缀最大值的数的个数,定义 \(B\) 为一个排列中是后缀最大 ...

  9. 【cf960G】G. Bandit Blues(第一类斯特林数)

    传送门 题意: 现在有一个人分别从\(1,n\)两点出发,包中有一个物品价值一开始为\(0\),每遇到一个价值比包中物品高的就交换两个物品. 现在已知这个人从左边出发交换了\(a\)次,从右边出发交换 ...

随机推荐

  1. kubernete 数据库 etcd

    etcdctl --cert-file /etc/ssl/etcd/ssl/member-pserver78.pem --key-file /etc/ssl/etcd/ssl/member-pserv ...

  2. 认识ASP.NET Windows身份认证

    本文摘自:细说ASP.NET Windows身份认证 Forms身份认证虽然使用广泛,不过,如果是在 Windows Active Directory 的环境中使用ASP.NET, 那么使用Windo ...

  3. (原创)odoo关系字段在视图中的行为控制 总结

    字段类型 选项或属性 格式示例 描述 many2one , many2many_tags(widget) no_create options='{"no_create":True} ...

  4. Sql_索引分析

    「索引就像书的目录, 通过书的目录就准确的定位到了书籍具体的内容」,这句话描述的非常正确, 但就像脱了裤子放屁,说了跟没说一样,通过目录查找书的内容自然是要比一页一页的翻书找来的快,同样使用的索引的人 ...

  5. restfull环境搭建-helloword(二)

    原文地址:http://only81.iteye.com/blog/1689537 本文描述,获取XML或json格式数据 首先,创建一个bean,比如Todo(JAXB自动将bean文件,转换成xm ...

  6. nginx try_files 详解

    server { listen ; server_name localhost; index index.html index.htm index.php; root /data/wwwroot; l ...

  7. M1/M2阶段总结

    之前提问的博客 问题解答 问题 1 关于代码复审,复审者是否应该参与编码?如果复审者也参与编码的话,那么难免任务量较多,但如果不参与编码的话,工作分配的似乎不太均衡. 我们的团队项目在M1和M2阶段没 ...

  8. svn 使用教程

    一.什么是SVN SVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于RCS.CVS,它采用了分支管理系统,它的设计目标就是取代CVS. 二.SVN的下载安装 下载地址:http ...

  9. 使用git命令创建分支到团队项目

    背景 在我们的团队中,我作为管理者,创建了一个叫HelloWorld的项目,大家各自在本地进行开发,将自己的工作贡献到我们的团队项目中.为了便于审核,我希望大家先将自己的贡献先放在属于自己的一个分支上 ...

  10. jupyter notebook远程配置

    服务器端配置 在服务器生成jupyter配置文件 $jupyter notebook --generate-config 生成之后会得到配置文件的路径 启动jupyter,设置密码 In [1]: f ...