Codeforces960G Bandit Blues 【斯特林数】【FFT】
题目大意:
求满足比之前的任何数小的有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】的更多相关文章
- 【CF960G】Bandit Blues(第一类斯特林数,FFT)
[CF960G]Bandit Blues(第一类斯特林数,FFT) 题面 洛谷 CF 求前缀最大值有\(a\)个,后缀最大值有\(b\)个的长度为\(n\)的排列个数. 题解 完完全全就是[FJOI] ...
- codeforces960G. Bandit Blues
题目链接:codeforces960G 来看看三倍经验:hdu4372 luogu4609 某蒟蒻的关于第一类斯特林数的一点理解QAQ:https://www.cnblogs.com/zhou2003 ...
- 【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≤ ...
- CF960G Bandit Blues 第一类斯特林数+分治+FFT
题目传送门 https://codeforces.com/contest/960/problem/G 题解 首先整个排列的最大值一定是 \(A\) 个前缀最大值的最后一个,也是 \(B\) 个后缀最大 ...
- CF960G Bandit Blues 【第一类斯特林数 + 分治NTT】
题目链接 CF960G 题解 同FJOI2016只不过数据范围变大了 考虑如何预处理第一类斯特林数 性质 \[x^{\overline{n}} = \sum\limits_{i = 0}^{n}\be ...
- CF960G Bandit Blues(第一类斯特林数)
传送门 可以去看看litble巨巨关于第一类斯特林数的总结 设\(f(i,j)\)为\(i\)个数的排列中有\(j\)个数是前缀最大数的方案数,枚举最小的数的位置,则有递推式\(f(i,j)=f(i- ...
- CF960G Bandit Blues 第一类斯特林数、NTT、分治/倍增
传送门 弱化版:FJOI2016 建筑师 由上面一题得到我们需要求的是\(\begin{bmatrix} N - 1 \\ A + B - 2 \end{bmatrix} \times \binom ...
- CF960G Bandit Blues 分治+NTT(第一类斯特林数)
$ \color{#0066ff}{ 题目描述 }$ 给你三个正整数 \(n\),\(a\),\(b\),定义 \(A\) 为一个排列中是前缀最大值的数的个数,定义 \(B\) 为一个排列中是后缀最大 ...
- 【cf960G】G. Bandit Blues(第一类斯特林数)
传送门 题意: 现在有一个人分别从\(1,n\)两点出发,包中有一个物品价值一开始为\(0\),每遇到一个价值比包中物品高的就交换两个物品. 现在已知这个人从左边出发交换了\(a\)次,从右边出发交换 ...
随机推荐
- sql实时提交事务
public void deleteByHbtlidAndDept(String class_id,String depart_id) { Session session = this.getHibe ...
- 在angularjs实现一个时钟
想在网页上,显示当前系统时钟. <body ng-app="App2" ng-controller="Ctrl2"> <div ng-bind ...
- 大话设计模式(C#)
还是那几句话: 学无止境,精益求精 十年河东,十年河西,莫欺少年穷 学历代表你的过去,能力代表你的现在,学习代表你的将来 问个问题: 如何写出高质量的代码?灵活,可扩展,易读,易维护,可重构,可复用. ...
- Luogu P2279 [HNOI2003]消防局的设立
这真的是一道SB题.去你的树形DP 我们看到题目就开始考虑贪心,怎么搞? 一个显然的思路,每次找出一个深度最大且未被覆盖的点,然后建一个消防局? 但这样的话,动用简单的人类思维就可以知道:我TM的还不 ...
- 51Nod 1705 七星剑
一道很新颖的概率DP,我看数据范围还以为是有指数级别的复杂度的呢 记得有人说期望要倒着推,但放在这道题上,就咕咕了吧. 我们考虑正着概率DP,设\(fi\)表示将剑升到\(i\)颗星花费的期望,这样我 ...
- [Oracle][Corruption]发生ORA00600[kdsgrp1]的时候,如何进行调查
本质上,这很可能是坏块引发的,所以需要调查 关联的Table 中的坏块状况: Excerpt of trace file============================*** 2017-08- ...
- 【转载】固态硬盘的S.M.A.R.T详解
文章来源于: 瑞耐斯存储技术 兵哥写这篇文章,是因为在测试的过程中看到了 SSD存在偶尔有性能下降的情况,经分析为S.M.A.R.T命令所导致,虽然这种情况看似不严重,但如果应用在诸如数据采集等关键性 ...
- inode 软/硬链接
一.inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统 ...
- Linux下部署Samba服务环境的操作记录
关于Linux和Windows系统之间的文件传输,很多人选择使用FTP,相对较安全,但是有时还是会出现一些问题,比如上传文件时,文件名莫名出现乱码,文件大小改变等问题.相比较来说,使用Samba作为文 ...
- curator 分布式锁InterProcessMutex
写这篇文章的目的主要是为了记录下自己在zookeeper 锁上踩过的坑,以及踩坑之后自己的一点认识; 从zk分布式锁原理说起,原理很简单,大家也应该都知道,简单的说就是zookeeper实现分布式锁是 ...