codeforces960G. Bandit Blues
题目链接:codeforces960G
某蒟蒻的关于第一类斯特林数的一点理解QAQ:https://www.cnblogs.com/zhou2003/p/10780832.html
注意到当前序列的最大值会对前缀最大值和后缀最大值均产生\(1\)的贡献
那么当我们去掉这个最大值后,剩下\(n-1\)个元素,需要产生\(a-1\)个前缀最大值和\(b-1\)个后缀最大值,并且它们的位置会以最大值为界限分布在两侧
我们将剩下的\(n-1\)个元素分成\((a-1)+(b-1)\)组,每一组钦定最大值在最开头,那么每一个这样的划分就对应了一个合法的序列,最后答案就是\(S(n-1,a+b-2)*\dbinom{a+b-2}{a-1}\),其中\(S(n,m)\)表示第一类斯特林数
这样你就可以完成后两题了
那么对于第一题呢?我们有这个式子:
\]
于是分治+FFT求之,据说有\(O(nlogn)\)的倍增做法?我懒啊
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define lowbit(x) (x)&(-x)
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,a,b) for (int i=a;i>=b;i--)
#define maxd 998244353
typedef long long ll;
const int N=100000;
const double pi=acos(-1.0);
int n,a,b,rev[400400];
ll s[20][400400];
int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
ll qpow(ll x,int y)
{
ll ans=1;
while (y)
{
if (y&1) ans=(ans*x)%maxd;
x=(x*x)%maxd;
y>>=1;
}
return ans;
}
ll inv(ll x) {return qpow(x,maxd-2);}
ll C(int n,int m)
{
if (n<m) return 0;
ll ans=1;
per(i,n,n-m+1) ans=ans*i%maxd;
rep(i,1,m) ans=ans*inv(i)%maxd;
return ans;
}
void ntt(int lim,ll *a,int typ)
{
rep(i,0,lim-1)
if (i<rev[i]) swap(a[i],a[rev[i]]);
int mid;
for (mid=1;mid<lim;mid<<=1)
{
ll wn=qpow(3,(maxd-1)/(mid<<1));
int len=(mid<<1),sta,j;
if (typ==-1) wn=inv(wn);
for (sta=0;sta<lim;sta+=len)
{
ll w=1;
for (j=0;j<mid;j++,w=(w*wn)%maxd)
{
ll x=a[sta+j],y=a[sta+j+mid]*w%maxd;
a[sta+j]=(x+y)%maxd;
a[sta+j+mid]=(x+maxd-y)%maxd;
}
}
}
if (typ==-1)
{
int invn=inv(lim);
rep(i,0,lim-1) a[i]=a[i]*invn%maxd;
}
}
void solve(int l,int r,int d)
{
if (l==r) {s[d][0]=l;s[d][1]=1;return;}
int mid=(l+r)>>1;
solve(l,mid,d+1);
rep(i,0,mid-l+1) s[d][i]=s[d+1][i];
solve(mid+1,r,d+1);
int lim=1,cnt=0;
while (lim<=(r-l+1)) {lim<<=1;cnt++;}
rep(i,mid-l+2,lim) s[d][i]=0;
rep(i,r-mid+1,lim) s[d+1][i]=0;
rep(i,0,lim-1)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
ntt(lim,s[d],1);ntt(lim,s[d+1],1);
rep(i,0,lim-1) s[d][i]=s[d][i]*s[d+1][i]%maxd;
ntt(lim,s[d],-1);
}
int main()
{
n=read();a=read();b=read();
if ((n-1<a+b-2) || (!a) || (!b)) {printf("0");return 0;}
if (n==1) {printf("1");return 0;}
solve(0,n-2,0);
printf("%lld",C(a+b-2,a-1)*s[0][a+b-2]%maxd);
return 0;
}
codeforces960G. Bandit Blues的更多相关文章
- Codeforces960G Bandit Blues 【斯特林数】【FFT】
题目大意: 求满足比之前的任何数小的有A个,比之后的任何数小的有B个的长度为n的排列个数. 题目分析: 首先写出递推式,设s(n,k)表示长度为n的排列,比之前的数小的数有k个. 我们假设新加入的数为 ...
- 【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 ...
- Luogu P4609 [FJOI2016]建筑师&&CF 960G Bandit Blues
考虑转化题意,我们发现其实就是找一个长度为\(n\)的全排列,使得这个排列有\(A\)个前缀最大值,\(B\)个后缀最大值,求方案数 我们考虑把最大值拎出来单独考虑,同时定义一些数的顺序排列为单调块( ...
- [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 ...
- 解题:CF960G Bandit Blues & FJOI 2016 建筑师
题面1 题面2 两个题推导是一样的,具体实现不一样,所以写一起了,以FJOI 2016 建筑师 的题面为标准 前后在组合意义下一样,现在只考虑前面,可以发现看到的这a个建筑将这一段划分成了a-1个区间 ...
- Codeforces 960G. Bandit Blues
Description 你需要构造一个长度为 \(n\) 的排列 , 使得一个数作为前缀最大值的次数为 \(A\) , 作为后缀最大值的次数为 \(B\) , 求满足要求的排列个数 . 题面 Solu ...
- CF960G Bandit Blues 【第一类斯特林数 + 分治NTT】
题目链接 CF960G 题解 同FJOI2016只不过数据范围变大了 考虑如何预处理第一类斯特林数 性质 \[x^{\overline{n}} = \sum\limits_{i = 0}^{n}\be ...
随机推荐
- 【转】Redis一般会遇到的问题以及解析
单线程的 Redis 为什么这么快 这个问题是对 Redis 内部机制的一个考察.根据我的面试经验,很多人都不知道Redis 是单线程工作模型.所以,这个问题还是应该要复习一下的. 回答主要是以下三点 ...
- hive基本操作与应用
通过hadoop上的hive完成WordCount 启动hadoop Hdfs上创建文件夹 上传文件至hdfs 启动Hive 创建原始文档表 导入文件内容到表docs并查看 用HQL进行词频统计,结果 ...
- 原生js实例对象方法
Array中的方法 ☞ toString() // 把数组转换为字符串,使用逗号分隔☞ valueOf() // 返回数组对象本身 ☞ 栈方法(先进后出)ary.push() // 该方法有一个返回值 ...
- 从0开始的Python学习014面向对象编程
简介 到目前为止,我们的编程都是根据数据的函数和语句块来设计的,面向过程的编程.还有一种我们将数据和功能结合起来使用对象的形式,使用它里面的数据和方法这种方法叫做面向对象的编程. 类和对象是面向对象 ...
- row_number() over()分页查询
1.首先讲下row_number() over() 是干什么的? 是一个分析函数,会在数据表生成一个排序列. 案例SQL: select ROW_NUMBER() over(order by book ...
- 关于MySQL集群的一些看法
作者:Gary Chen链接:https://zhuanlan.zhihu.com/p/20204156来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 市面上的招聘往往 ...
- JSX有感
开发一个网页,我们要写视图部分HTML,也要写交互逻辑JS. 写JS时,不断翻看HTML,确保querySelector能取到期望的元素. 改HTML时,一个个排查JS文件,确保其没受影响. -- 类 ...
- vue笔记未整理
全局组件 局部组件 子组件传值到父组件 父子组件传值 watch跟计算属性差不多,都会有缓存,计算属性优先 计算属性get set 对象 数组 对象 数组 不复用 改变数组 直接修改数组,页面没变化 ...
- CentOS 安装 ceph 单机版(luminous版本)
一.环境准备 CentOS Linux release 7.4.1708 (Core)一台,4块磁盘(sda.sdb,.sdc.sdd) 192.168.27.130 nceph 二.配置环境 1.修 ...
- C# 中利用 CRC32 值判断文件是否重复
需要在 NuGet 中引用 Crc32.NET 包 直接贴代码了: using Force.Crc32; using System; using System.Collections.Generic; ...