CF960G-Bandit Blues【第一类斯特林数,分治,NTT】
正题
题目链接:https://www.luogu.com.cn/problem/CF960G
题目大意
求有多少个长度为\(n\)的排列,使得有\(A\)个前缀最大值和\(B\)个后缀最大值。
\(0\leq n,A,B\leq 10^5\)
解题思路
显然的是把最大的数两边然后左边的是前缀最大值,右边的是前缀最小值。
然后考虑两个前缀最大值之间其实可以插任何数字,但是最大的一定要排在前面。
其实就是这些数字分成若干个圆排列的个数,就是第一类斯特林数。
枚举左右两边的数量就有
\]
然后组合意义理解一下,我们可以考虑直接分成\(a+b-2\)个环然后再依次排列到左右就是
\]
这个看起来就好做很多,先考虑怎么求第一类斯特林数。
考虑递推式
\]
可以理解为\(0\sim n-1\)个里面选出\(m\)个数的乘积之和。
用生成函数做就是
\]
用分治+\(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】的更多相关文章
- CF960G Bandit Blues 第一类斯特林数、NTT、分治/倍增
传送门 弱化版:FJOI2016 建筑师 由上面一题得到我们需要求的是\(\begin{bmatrix} N - 1 \\ A + B - 2 \end{bmatrix} \times \binom ...
- [CF960G]Bandit Blues(第一类斯特林数+分治卷积)
Solution: 先考虑前缀,设 \(f(i, j)\) 为长度为 \(i\) 的排列中满足前缀最大值为自己的数有 \(j\) 个的排列数. 假设新加一个数 \(i+1\) 那么会有: \[ f ...
- 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 ...
- Codeforces960G Bandit Blues 【斯特林数】【FFT】
题目大意: 求满足比之前的任何数小的有A个,比之后的任何数小的有B个的长度为n的排列个数. 题目分析: 首先写出递推式,设s(n,k)表示长度为n的排列,比之前的数小的数有k个. 我们假设新加入的数为 ...
- CF960G Bandit Blues 分治+NTT(第一类斯特林数)
$ \color{#0066ff}{ 题目描述 }$ 给你三个正整数 \(n\),\(a\),\(b\),定义 \(A\) 为一个排列中是前缀最大值的数的个数,定义 \(B\) 为一个排列中是后缀最大 ...
- 【CF960G】Bandit Blues(第一类斯特林数,FFT)
[CF960G]Bandit Blues(第一类斯特林数,FFT) 题面 洛谷 CF 求前缀最大值有\(a\)个,后缀最大值有\(b\)个的长度为\(n\)的排列个数. 题解 完完全全就是[FJOI] ...
- CF960G Bandit Blues(第一类斯特林数)
传送门 可以去看看litble巨巨关于第一类斯特林数的总结 设\(f(i,j)\)为\(i\)个数的排列中有\(j\)个数是前缀最大数的方案数,枚举最小的数的位置,则有递推式\(f(i,j)=f(i- ...
- 【cf960G】G. Bandit Blues(第一类斯特林数)
传送门 题意: 现在有一个人分别从\(1,n\)两点出发,包中有一个物品价值一开始为\(0\),每遇到一个价值比包中物品高的就交换两个物品. 现在已知这个人从左边出发交换了\(a\)次,从右边出发交换 ...
随机推荐
- C#多线程---Semaphore实现线程同步
一.简介 Semaphore类限制可同时访问某一资源或资源池的线程数.线程通过调用 WaitOne方法将信号量减1,并通过调用 Release方法把信号量加1. 构造函数:public Semapho ...
- RabbitMq死信队列(接盘侠)
队列创建之后,后期对其修改或者参数添加会报错.需要把队列重新删除,重新创建线上环境不能把队列删除,优雅安全的方式是重新建一个队列,把死信队列相关的队列进行绑定 在有过期时间的队列中设定最大接收能力5条 ...
- 初步测试VS2017+Win10IoT,基于World Map of Makers
测试World Map of Makers Demo,创建一个简单的internet连接应用程序来查询web API的状态(目测是一个延时时间),并使用该信息切换LED. 官方仓库的Solution是 ...
- java线程池-工作队列workQueue
线程池之工作队列 ArrayBlockingQueue 采用数组来实现,并采用可重入锁ReentrantLock来做并发控制,无论是添加还是读取,都先要获得锁才能进行操作 可看出进行读写操作都使用了R ...
- MySQL——备份与恢复
MySQL数据库备份和恢复 --备份类型: 1.热备份(只有InnoDB支持)(不影响业务,最好的方式) 2.冷备份( 阻止用户访问) 3.温备份 --备份方式: 1.逻辑备份(文本表示:SQL语句) ...
- Django实现基本的页面分页
1.视图views.py from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage def index(requ ...
- Mysql常用sql语句(15)- cross join 交叉连接
测试必备的Mysql常用sql语句 https://www.cnblogs.com/poloyy/category/1683347.html 前言 交叉连接就是求多表之间的笛卡尔积 讲道理..这个我都 ...
- Element UI:级联选择器Cascader_动态加载_多级请求不同接口(已知第一级调取第二级)
ELEMENT UI_CASCADER 使用过饿了么级联动态加载的小伙伴应该都知道,lazyLoad本身是一个无差别返回渲染结点的函数. 当我们存在一个需求:已知级联选择器的第一级结点,现在需要通过第 ...
- excel中if函数的用法
IF函数有三个参数,语法如下: =IF(条件判断, 结果为真返回值, 结果为假返回值) 第一参数是条件判断,比如说"A1="百度""或"21>3 ...
- android开发使用jxl创建Excel
这周水了几天,今天把博客赶上,找找状态. 周五的时候终于完成了课堂测试第二阶段,主要的难点就是生成Excel表并将填写的数据插入到Excel表中. 一.jxl使用 1.创建或读取一个工作薄 Workb ...