CF960G
首先我们考虑$n$的情况,显然以$n$为分界线可以将整个序列分成两部分,就像这样:
、
那么我们考虑:在这个东西前面才会有前缀最大的统计,在这个东西后面才会有后缀最大的统计
这样就剩下了$n-1$个元素,而我们需要把这$n-1$个元素分成$A+B-2$个集合,然后把每个集合的最大的一个放在一端,然后剩余部分全排列
设一个集合中有$k$个元素,那么剩余元素全排列的方案数就是$(k-1)!$
考虑这也是对$k$个元素放在一个圆排列上的方案数,因此我们能搞出一个第一类斯特林数的表达式:
$S_{1}(n-1,A+B-2)$
然后考虑这几个集合在左右的分布,有:$C_{A+B-2}^{A-1}$
因此最终答案即为$S_{1}(n-1,A+B-2)C_{A+B-2}^{A-1}$
然后第一类斯特林数可以倍增$O(nlog_{2}n)$求解,因此能通过这题:
// luogu-judger-enable-o2
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define ll unsigned long long
#define uint unsigned int
using namespace std;
const uint mode=998244353;
uint pow_mul(uint x,uint y)
{
uint ret=1;
while(y)
{
if(y&1)ret=1ll*ret*x%mode;
x=1ll*x*x%mode,y>>=1;
}
return ret;
}
uint inv[300005],minv[300005],mul[300005];
void init()
{
inv[0]=inv[1]=minv[0]=minv[1]=mul[0]=mul[1]=1;
for(uint i=2;i<=300000;i++)
{
inv[i]=1ll*(mode-mode/i)*inv[mode%i]%mode;
minv[i]=1ll*minv[i-1]*inv[i]%mode;
mul[i]=1ll*mul[i-1]*i%mode;
}
}
uint MOD(uint x,uint y)
{
return x+y>=mode?x+y-mode:x+y;
}
uint to[(1<<20)+5];
uint n,a,b;
void NTT(uint *a,uint len,int k)
{
for(uint i=0;i<len;i++)if(i<to[i])swap(a[i],a[to[i]]);
for(uint i=1;i<len;i<<=1)
{
uint w0=pow_mul(3,(mode-1)/(i<<1));
for(uint j=0;j<len;j+=(i<<1))
{
uint w=1;
for(uint o=0;o<i;o++,w=1ll*w*w0%mode)
{
ll w1=a[j+o],w2=1ll*a[j+o+i]*w%mode;
a[j+o]=MOD(w1,w2)%mode,a[j+o+i]=MOD(mode-w2,w1);
}
}
}
if(k==-1)
{
uint inv=pow_mul(len,mode-2);
for(uint i=1;i<(len>>1);i++)swap(a[i],a[len-i]);
for(uint i=0;i<len;i++)a[i]=1ll*a[i]*inv%mode;
}
}
uint A[(1<<20)+5],B[(1<<20)+5],C[(1<<20)+5];
uint tempt[(1<<20)+5],tempf[(1<<20)+5],tempg[(1<<20)+5],tempG[(1<<20)+5],tempF[(1<<20)+5];
uint ret[(1<<20)+5];
void mult(uint *f,uint *g,uint len)
{
uint lim=1,l=0;
while(lim<=2*(len+1))lim<<=1,l++;
for(uint i=0;i<lim;i++)to[i]=((to[i>>1]>>1)|((i&1)<<(l-1)));
for(uint i=0;i<lim;i++)A[i]=B[i]=0;
for(uint i=0;i<=len;i++)A[i]=f[i],B[i]=g[i];
for(uint i=0;i<lim;i++)C[i]=0;
NTT(A,lim,1),NTT(B,lim,1);
for(uint i=0;i<lim;i++)C[i]=1ll*A[i]*B[i]%mode;
NTT(C,lim,-1);
}
void solve(uint *g,uint dep)
{
if(!dep){g[0]=1;return;}
if(dep==1)
{
g[0]=0,g[1]=1;
return;
}
if(dep&1)
{
solve(g,dep-1);
for(uint i=1;i<=dep;i++)tempG[i]=C[i-1];
for(uint i=0;i<dep;i++)tempG[i]=MOD(tempG[i],1ll*C[i]*(dep-1)%mode);
for(uint i=0;i<=dep;i++)g[i]=tempG[i];
}else
{
uint mid=(dep>>1);
solve(g,mid);
uint temp=1;
for(uint i=0;i<=mid;i++,temp=1ll*temp*mid%mode)tempg[i]=1ll*g[mid-i]*mul[mid-i]%mode,tempf[i]=1ll*temp*minv[i]%mode;
mult(tempg,tempf,mid);
for(uint i=0;i<=mid;i++)tempF[i]=1ll*C[mid-i]*minv[i]%mode;
mult(tempF,g,mid);
for(uint i=0;i<=dep;i++)g[i]=C[i];
}
}
uint get_C(uint x,uint y)
{
if(x<y)return 0;
return 1ll*mul[x]*minv[y]%mode*minv[x-y]%mode;
}
int main()
{
scanf("%u%u%u",&n,&a,&b);init();
solve(ret,n-1);
printf("%u\n",1ll*ret[a+b-2]*get_C(a+b-2,a-1)%mode);
return 0;
}
CF960G的更多相关文章
- 【CF960G】Bandit Blues(第一类斯特林数,FFT)
[CF960G]Bandit Blues(第一类斯特林数,FFT) 题面 洛谷 CF 求前缀最大值有\(a\)个,后缀最大值有\(b\)个的长度为\(n\)的排列个数. 题解 完完全全就是[FJOI] ...
- CF960G Bandit Blues 【第一类斯特林数 + 分治NTT】
题目链接 CF960G 题解 同FJOI2016只不过数据范围变大了 考虑如何预处理第一类斯特林数 性质 \[x^{\overline{n}} = \sum\limits_{i = 0}^{n}\be ...
- 【CF960G】Bandit Blues
[CF960G]Bandit Blues 题面 洛谷 题解 思路和这道题一模一样,这里仅仅阐述优化的方法. 看看答案是什么: \[ Ans=C(a+b-2,a-1)\centerdot s(n-1,a ...
- CF960G(第一类斯特林数)
题目 CF960G 做法 设\(f(i,j)\)为\(i\)个数的序列,有\(j\)个前缀最大值的方案数 我们考虑每次添一个最小数,则有:\(f(i,j)=f(i-1,j)+(i-1)*f(i-1,j ...
- [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个区间 ...
- CF960G Bandit Blues 分治+NTT(第一类斯特林数)
$ \color{#0066ff}{ 题目描述 }$ 给你三个正整数 \(n\),\(a\),\(b\),定义 \(A\) 为一个排列中是前缀最大值的数的个数,定义 \(B\) 为一个排列中是后缀最大 ...
- CF960G Bandit Blues(第一类斯特林数)
传送门 可以去看看litble巨巨关于第一类斯特林数的总结 设\(f(i,j)\)为\(i\)个数的排列中有\(j\)个数是前缀最大数的方案数,枚举最小的数的位置,则有递推式\(f(i,j)=f(i- ...
- 【cf960G】G. Bandit Blues(第一类斯特林数)
传送门 题意: 现在有一个人分别从\(1,n\)两点出发,包中有一个物品价值一开始为\(0\),每遇到一个价值比包中物品高的就交换两个物品. 现在已知这个人从左边出发交换了\(a\)次,从右边出发交换 ...
随机推荐
- 20203412马畅若 实验三 《Python程序设计》Socket编程技术实验报告
实验三 Socket编程技术 课程:<Python程序设计>班级: 2034姓名: 马畅若学号:20203412实验教师:王志强实验日期:2020年5月30日必修/选修: 公选课 ##1. ...
- Quartz 2D实现文字镂空效果
什么是镂空效果,下图就是一个镂空效果的文字: 从图可知,文字是透明的,可以看到下面的图片内容,而UILabel其它部分是白色背景. 使用Quartz 2D绘制镂空效果,大体思路如下: 实现一个UILa ...
- 问题记录_IDEA启动报错:Failed to create JVM. JVM Path
问题记录_IDEA启动报错:Failed to create JVM. JVM Path 起因 下午写代码的时候感觉IDEA有点卡,不应该啊,我16G咋回卡呢,分配的内存也不小,于是又去加大内存分配, ...
- ES 基础操作
集群 健康值的三种状态 Green:所有索引的所有分片均可用 primary 和 replice 均可用. Yellow 至少有一个 replice不可以用, 但是所有的 primary 正常. Re ...
- ORA-01653:unable to extend table xxxxx by 8192 in tablespace xxxxx
原因:表空间满 解决:扩展表空间 报错截图: 参考摘录:https://blog.csdn.net/qq_35257875/article/details/90295272
- git的相关命令
1.将文件添加至版本库的暂存区(stage)的命令是git add 1.1. 添加完所有有被修改的文件:git add . 1.2. 添加指定文件:git add 指定文件 2.将文件提交至本地仓库 ...
- cgroup与docker
1.使用 cgroup namespace 需要内核开启 CONFIG_CGROUPS 选项.可通过以下方式验证: 1 root@container:~/namespace_test# grep CO ...
- 【服务器数据恢复】HP EVA存储多块硬盘离线的数据恢复案例
服务器故障&检测&分析:某品牌EVA存储设备中的RAID5磁盘有两块硬盘掉线,lun丢失.硬件工程师对故障服务器进行物理故障检测,发现掉线硬盘能够正常读取,无物理故障,也没有发现坏道. ...
- 【服务器数据恢复】热备盘同步失败导致数据丢失的raid5数据恢复案例
服务器数据恢复环境:华为s系列服务器:24块硬盘组成一组raid5磁盘阵列,其中包含1块热备盘. 服务器故障&检测:服务器工作状态下raid5中有一块硬盘离线,热备盘激活替换离线硬盘并开始进行 ...
- 【Java学习Day08】数据类型、变量及字节
数据类型 强类型语言 要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用 弱类型语言 要求变量的使用要符合规定,所有变量都必须先定义后才能使用 Java的两大数据类型 public clas ...