正题

题目链接:https://www.luogu.com.cn/problem/CF960G


题目大意

求有多少个长度为\(n\)的排列,使得有\(A\)个前缀最大值和\(B\)个后缀最大值。

\(0\leq n,A,B\leq 10^5\)


解题思路

显然的是把最大的数两边然后左边的是前缀最大值,右边的是前缀最小值。

然后考虑两个前缀最大值之间其实可以插任何数字,但是最大的一定要排在前面。

其实就是这些数字分成若干个圆排列的个数,就是第一类斯特林数。

枚举左右两边的数量就有

\[\sum_{i=0}^{n-1}\begin{bmatrix}i\\a-1\end{bmatrix}\begin{bmatrix}n-i-1\\b-1\end{bmatrix}\binom{n-1}{i}
\]

然后组合意义理解一下,我们可以考虑直接分成\(a+b-2\)个环然后再依次排列到左右就是

\[\begin{bmatrix}n-1\\a+b-2\end{bmatrix}\binom{a+b-2}{a-1}
\]

这个看起来就好做很多,先考虑怎么求第一类斯特林数。

考虑递推式

\[\begin{bmatrix}n\\m\end{bmatrix}=\begin{bmatrix}n-1\\m-1\end{bmatrix}+\begin{bmatrix}n-1\\m\end{bmatrix}\times(n-1)
\]

可以理解为\(0\sim n-1\)个里面选出\(m\)个数的乘积之和。

用生成函数做就是

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

用分治+\(NTT\)算就好了,当然推式子还有更快的方法

时间复杂度\(O(n\log^2 n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=4e5+10,P=998244353;
struct Poly{
ll f[N];ll n;
}F[20];
ll n,a,b,f[N],g[N],r[N];bool use[20];
ll power(ll x,ll b){
ll ans=1;
while(b){
if(b&1)ans=ans*x%P;
x=x*x%P;b>>=1;
}
return ans;
}
void NTT(ll *f,ll n,ll op){
for(ll i=0;i<n;i++)
if(i<r[i])swap(f[i],f[r[i]]);
for(ll p=2;p<=n;p<<=1){
ll tmp=power(3,(P-1)/p),len=p>>1;
if(op==-1)tmp=power(tmp,P-2);
for(ll k=0;k<n;k+=p){
ll buf=1;
for(ll i=k;i<k+len;i++){
ll tt=f[i+len]*buf%P;
f[i+len]=(f[i]-tt+P)%P;
f[i]=(f[i]+tt)%P;
buf=buf*tmp%P;
}
}
}
if(op==-1){
ll invn=power(n,P-2);
for(ll i=0;i<n;i++)
f[i]=f[i]*invn%P;
}
return;
}
void mul(Poly &x,Poly &y){
ll n=1;while(n<x.n+y.n)n<<=1;
for(ll i=0;i<n;i++)r[i]=(r[i>>1]>>1)|((i&1)?(n>>1):0);
for(ll i=0;i<n;i++)f[i]=x.f[i],g[i]=y.f[i];
NTT(f,n,1);NTT(g,n,1);
for(ll i=0;i<n;i++)f[i]=f[i]*g[i]%P;
NTT(f,n,-1);
for(ll i=0;i<n;i++)x.f[i]=f[i],y.f[i]=0;
x.n=x.n+y.n-1;return;
}
ll FindE(){
for(ll i=0;i<20;i++)
if(!use[i])return i;
}
ll solve(ll l,ll r){
if(l==r){
ll p=FindE();
F[p].f[0]=l;F[p].f[1]=1;
F[p].n=2;use[p]=1;return p;
}
ll mid=(l+r)>>1;
ll ls=solve(l,mid),rs=solve(mid+1,r);
mul(F[ls],F[rs]);use[rs]=0;return ls;
}
ll C(ll n,ll m){
ll ans=1,fac=1;
for(ll i=m+1;i<=n;i++)ans=ans*i%P;
for(ll i=1;i<=n-m;i++)fac=fac*i%P;
return ans*power(fac,P-2)%P;
}
signed main()
{
scanf("%lld%lld%lld",&n,&a,&b);
if(!a||!b||a+b-2>n-1)return puts("0")&0;
if(n==1)return puts("1")&0;
ll p=solve(0,n-2);
printf("%lld\n",F[p].f[a+b-2]*C(a+b-2,a-1)%P);
return 0;
}

CF960G-Bandit Blues【第一类斯特林数,分治,NTT】的更多相关文章

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

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

  2. [CF960G]Bandit Blues(第一类斯特林数+分治卷积)

    Solution: ​ 先考虑前缀,设 \(f(i, j)\) 为长度为 \(i\) 的排列中满足前缀最大值为自己的数有 \(j\) 个的排列数. 假设新加一个数 \(i+1\) 那么会有: \[ f ...

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

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

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

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

  5. Codeforces960G Bandit Blues 【斯特林数】【FFT】

    题目大意: 求满足比之前的任何数小的有A个,比之后的任何数小的有B个的长度为n的排列个数. 题目分析: 首先写出递推式,设s(n,k)表示长度为n的排列,比之前的数小的数有k个. 我们假设新加入的数为 ...

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

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

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

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

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

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

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

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

随机推荐

  1. WindowsService开发简单入门

    参考网址: https://www.cnblogs.com/wenlong512/p/7355971.html 一.简介 程序创建在 Windows 会话中,可长时间运行的可执行应用程序.这些服务可以 ...

  2. SpringBoot五步配置Mybatis

    第一步:Maven里面添加mybatis的引用jar包: <!--mybatis--> <dependency> <groupId>org.mybatis.spri ...

  3. Java程序设计学习笔记(三)—— IO

    时间:2016-3-24 11:02 --IO流(Input/Output)     IO流用来处理设备之间的数据传输.    Java对数据的操作是通过流的方式.    Java对于操作流的对象都在 ...

  4. Storm重启topology,失败

    storm新加节点,重启topology后,出现错误 如果检查了CPU和内存不高后,还出现 java.lang.OutOfMemoryError: unable to create new nativ ...

  5. vscode 1.32.x按下鼠标左键无法拖曳选择,而旧一点的版本1.30.2可以

    最近升级vscode后,无法通过鼠标左键选择文本,恢复到旧版本1.30.2就可以了. 另外:1.32.x和1.31.1都不正常 进一步测试发现:在中文输入法下(无论中英输入模式),都有问题:切换到纯英 ...

  6. plsql中数据生成工具data generator的使用

    使用数据库时,有时需要使用大量的数据,可以用PLSQL Developer提供的Data Generator工具, 这里记录一下工具的介绍及几个使用注意事项 1.工具介绍 功能入口位于 工具 菜单下, ...

  7. Python中的文件处理和数据存储json

    前言:每当需要分析或修改存储在文件中的信息时,读取文件都很有用,对数据分析应用程序来说尤其如此. 例如,你可以编写一个这样的程序:读取一个文本文件的内容,重新设置这些数据的格式并将其写入文件,让浏览器 ...

  8. 小程序 读取照片 EXIF 元信息

    安装 exif.js npm install exif-js --save UI <button type="primary" @click="onExif&quo ...

  9. idea配置tomcat及中文乱码解决

    放在前面:不要使用tomcat10,访问自己的页面会报404错误,目前无解,在这个坑爬了一下午,最终换了tomcat 9才解决.所以我选择了tomcat 9 + idea 2021.2版本 配置步骤: ...

  10. ABP 极简入门教程(二 MVC方式显示数据)

    增加显示菜单 Sample.Web.MVC项目中找到startup目录打开SampleNavigationProvider.cs,根据现有内容添加以下内容 .AddItem( new MenuItem ...