Codeforces 960G. Bandit Blues
Description
你需要构造一个长度为 \(n\) 的排列 , 使得一个数作为前缀最大值的次数为 \(A\) , 作为后缀最大值的次数为 \(B\) , 求满足要求的排列个数 .
题面
Solution
同 \(FJOI\) 建筑师 .
从 \(n\) 到 \(1\) 依次加入 , 对于 \(n\) ,对 \(A,B\) 的出现次数都会贡献 \(1\) .
剩下的数 , 如果放在左边则对 \(A\) 有贡献 , 放在右边则对 \(B\) 有贡献 , 放在中间则没有贡献 .
我们从组合意义上分析 , 那么相当于是操作 \(n-1\) 轮 , 每轮可以选择 从 \((0,0)\) 向走 \((A-1,B-1)\) 一步或者停顿的方案数 .
从 \((0,0)\) 走向 \((A-1,B-1)\) 的不同方案数为 \(C(A+B-2,A-1)\)
并且还要求出分配停顿的位置(确定每个位置停了几次)的不同方案数 .
这个可以 \(DP\) 设前 \(i\) 次操作 , 走了 \(j\) 步的方案数, \(f[i][j]=f[i-1][j-1]+f[i-1][j]*(i-1)\) , 这个东西就等于第一类斯特林数 .
由于\(S(n,m)\)等于 \(P(x,n)\) 的第 \(x^m\) 项系数 , 就可以对应一个上升幂的 \(x^m\) 项系数.
可以分治+\(NTT\) 合并出一个长度为 \(n\) 的多项式 , 就可以求出第一类斯特林数的某一行了 .
#include<bits/stdc++.h>
using namespace std;
template<class T>void gi(T &x){
int f;char c;
for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
}
const int N=4e5+10,mod=998244353;
inline int qm(int x,int k){
int sum=1;
for(;k;k>>=1,x=1ll*x*x%mod)if(k&1)sum=1ll*sum*x%mod;
return sum;
}
int n,a[20][N],R[N],L=0;
inline int C(int n,int m){
if(n<m || n<0 || m<0)return 0;
int ret=1,I=1;
for(int i=1;i<=m;i++)ret=1ll*ret*(n-i+1)%mod,I=1ll*I*i%mod;
return 1ll*ret*qm(I,mod-2)%mod;
}
inline void NTT(int *A){
for(int i=0;i<n;i++)if(i<R[i])swap(A[i],A[R[i]]);
for(int i=1;i<n;i<<=1){
int t0=qm(3,(mod-1)/(i<<1)),x,y;
for(int j=0;j<n;j+=i<<1){
int t=1;
for(int k=0;k<i;k++,t=1ll*t*t0%mod){
x=A[j+k];y=1ll*A[j+k+i]*t%mod;
A[j+k]=(x+y)%mod;A[j+k+i]=(x-y+mod)%mod;
}
}
}
}
inline void mul(int *A,int *B){
NTT(A);NTT(B);
for(int i=0;i<n;i++)A[i]=1ll*A[i]*B[i]%mod;
NTT(A);reverse(A+1,A+n);
for(int i=0,t=qm(n,mod-2);i<n;i++)A[i]=1ll*A[i]*t%mod;
}
inline void solve(int l,int r,int d){
if(l==r){a[d][0]=l;a[d][1]=1;return ;}
int mid=(l+r)>>1,m=r-l+1;
solve(l,mid,d+1);
for(int i=0;i<=m;i++)a[d][i]=a[d+1][i];
solve(mid+1,r,d+1);
for(n=1,L=0;n<=m;n<<=1)L++;
for(int i=mid-l+2;i<n;i++)a[d][i]=0;
for(int i=r-mid+1;i<n;i++)a[d+1][i]=0;
for(int i=0;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
mul(a[d],a[d+1]);
}
int A,B;
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
cin>>n>>A>>B;
if(n==1){
if(A+B-2>=0)puts("1");else puts("0");
exit(0);
}
solve(0,n-2,0);
cout<<1ll*a[0][A+B-2]*C(A+B-2,A-1)%mod;
return 0;
}
Codeforces 960G. Bandit Blues的更多相关文章
- Luogu P4609 [FJOI2016]建筑师&&CF 960G Bandit Blues
考虑转化题意,我们发现其实就是找一个长度为\(n\)的全排列,使得这个排列有\(A\)个前缀最大值,\(B\)个后缀最大值,求方案数 我们考虑把最大值拎出来单独考虑,同时定义一些数的顺序排列为单调块( ...
- 【CF960G】Bandit Blues(第一类斯特林数,FFT)
[CF960G]Bandit Blues(第一类斯特林数,FFT) 题面 洛谷 CF 求前缀最大值有\(a\)个,后缀最大值有\(b\)个的长度为\(n\)的排列个数. 题解 完完全全就是[FJOI] ...
- 【CF960G】Bandit Blues
[CF960G]Bandit Blues 题面 洛谷 题解 思路和这道题一模一样,这里仅仅阐述优化的方法. 看看答案是什么: \[ Ans=C(a+b-2,a-1)\centerdot s(n-1,a ...
- Divide by Zero 2018 and Codeforces Round #474 (Div. 1 + Div. 2, combined)G - Bandit Blues
题意:求满足条件的排列,1:从左往右会遇到a个比当前数大的数,(每次遇到更大的数会更换当前数)2.从右往左会遇到b个比当前数大的数. 题解:1-n的排列,n肯定是从左往右和从右往左的最后一个数. 考虑 ...
- CF960G Bandit Blues 第一类斯特林数+分治+FFT
题目传送门 https://codeforces.com/contest/960/problem/G 题解 首先整个排列的最大值一定是 \(A\) 个前缀最大值的最后一个,也是 \(B\) 个后缀最大 ...
- codeforces960G. Bandit Blues
题目链接:codeforces960G 来看看三倍经验:hdu4372 luogu4609 某蒟蒻的关于第一类斯特林数的一点理解QAQ:https://www.cnblogs.com/zhou2003 ...
- [CF960G] Bandit Blues
题意 给你三个正整数 \(n,a,b\),定义 \(A\) 为一个排列中是前缀最大值的数的个数,定义 \(B\) 为一个排列中是后缀最大值的数的个数,求长度为 \(n\) 的排列中满足 \(A = a ...
- CF960G Bandit Blues 第一类斯特林数、NTT、分治/倍增
传送门 弱化版:FJOI2016 建筑师 由上面一题得到我们需要求的是\(\begin{bmatrix} N - 1 \\ A + B - 2 \end{bmatrix} \times \binom ...
- Codeforces960G Bandit Blues 【斯特林数】【FFT】
题目大意: 求满足比之前的任何数小的有A个,比之后的任何数小的有B个的长度为n的排列个数. 题目分析: 首先写出递推式,设s(n,k)表示长度为n的排列,比之前的数小的数有k个. 我们假设新加入的数为 ...
随机推荐
- think in java 手记(一)
工作之余,不知道要做些什么.该做的事情都完成的差不多了,想看一下spring的东西,毕竟这些东西用的多.但是又想看一下关于javaee的东西,这个里面的设计模式多.想了一会儿,觉得这些无非都是工具,j ...
- 学习Spring Data JPA
简介 Spring Data 是spring的一个子项目,在官网上是这样解释的: Spring Data 是为数据访问提供一种熟悉且一致的基于Spring的编程模型,同时仍然保留底层数据存储的特殊 ...
- MVC批量上传文件
初始图片: 选中图片后 ---------------------------------------------------------------------------------- 前端代码 ...
- java poi 获取单元格值时间
完整帮助类:JAVA poi 帮助类 /* * poi特殊日期格式:数字格式化成-yyyy年MM月dd日,格式 * */ private static ArrayList<String> ...
- C#不用union,而是有更好的方式实现
用过C/C++的人都知道有个union,特别好用,似乎char数组到short,int,float等的转换无所不能,也确实是能,并且用起来十分方便.那C#为什么没有这个关键字呢?怎么实现这个功能?其实 ...
- Eclipse设置代理
Windows->Preferences->General->Network Connections下面可以设置代理 如果要指定特定的代理地址,需要把类型改为Manual 通常htt ...
- 初识GitHub与Git
在初次接触GitHub的时候,英语渣渣本渣真是深感无奈啊..... ORZ 在好友的帮助下,也算是初步入门了吧. 谨以此文作为初级使用手册记录,希望能帮助到你. 一.首先要申请一个GitHub账户 二 ...
- poj 3250 Bad Hair Day(栈的运用)
http://poj.org/problem?id=3250 Bad Hair Day Time Limit: 2000MS Memory Limit: 65536K Total Submissi ...
- Kettle 使用入门
Kettle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行,数据抽取高效稳定. 本文介绍一个入门例子:使用Kettle从动态指定的文件名对应的文本文件里抽取 ...
- Android 导入 aar 库文件
1. 在需要导入 aar 的 module 目录下创建一个名叫 "aars" 的目录,并把 aar 文件复制到这里. 2. 在项目的 build.gradle 文件里添加 allp ...