首先我们考虑$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的更多相关文章

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

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

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

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

  3. 【CF960G】Bandit Blues

    [CF960G]Bandit Blues 题面 洛谷 题解 思路和这道题一模一样,这里仅仅阐述优化的方法. 看看答案是什么: \[ Ans=C(a+b-2,a-1)\centerdot s(n-1,a ...

  4. CF960G(第一类斯特林数)

    题目 CF960G 做法 设\(f(i,j)\)为\(i\)个数的序列,有\(j\)个前缀最大值的方案数 我们考虑每次添一个最小数,则有:\(f(i,j)=f(i-1,j)+(i-1)*f(i-1,j ...

  5. [CF960G] Bandit Blues

    题意 给你三个正整数 \(n,a,b\),定义 \(A\) 为一个排列中是前缀最大值的数的个数,定义 \(B\) 为一个排列中是后缀最大值的数的个数,求长度为 \(n\) 的排列中满足 \(A = a ...

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

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

  7. 解题:CF960G Bandit Blues & FJOI 2016 建筑师

    题面1 题面2 两个题推导是一样的,具体实现不一样,所以写一起了,以FJOI 2016 建筑师 的题面为标准 前后在组合意义下一样,现在只考虑前面,可以发现看到的这a个建筑将这一段划分成了a-1个区间 ...

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

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

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

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

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

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

随机推荐

  1. java开发常用软件下载

    1.idea工具下载:https://www.jetbrains.com/idea/download/#section=windows 2.dbeaver下载:https://dbeaver.io  ...

  2. (0303)怎么在sequence中调用agent中的函数以及如何快速实验你的想法?

    https://mp.weixin.qq.com/s/9hDz9-nur5szBib18_yPnA

  3. java基础(一)~~内存分析

    1.java内存分析 2.2.面向对象内存分析 Java虚拟机的内存可以分为三个区域:栈(stack).堆(heap).方法区(method area): 2.2.1.栈 栈的特点如下: 1.栈描述的 ...

  4. Typora以及Markdown学习

    Typora以及Markdown学习 标题 n级标题 一级标题为#+[空格]+标题或者ctrl+1 二级标题则为``##+[空格]+标题`或者ctrl+2 后续几级标题依此类推... 最多支持6级标题 ...

  5. Antlr语法优化过程记录

    背景 Modelica Spec中的语法文件在Antlr下表现很糟糕,至少是1个数量级的糟糕的性能表现 理论 语义谓词减慢速度 ATN图中多分支转换为单分支 可选放在词法开头和语法的结尾 避免前导可选 ...

  6. guava冲突导致的报错

    Exception in thread "main" java.lang.IllegalAccessError: tried to access method com.google ...

  7. notepad++设置

    1.背景颜色 [设置]-[语言格式设置] 选择主题:Solarized-light

  8. windows sshd powershell 配置

    安装sshd打开"设置",选择"应用">"应用和功能",然后选择"可选功能" .扫描列表,查看是否已安装 Open ...

  9. Quartus II 17.1新建一个流水灯

    诸图排序:从左到右,从上到下 一.软件设置 1.新建工程并添加FPGA芯片 2.新建.v文件并添加至顶层实体 3.元器件特性设置 4.分析与阐述(生成网表文件) 5.引脚分配 6.编译(包含分析与综合 ...

  10. @order(1)

    @order(num),数字表示加载顺序 1.AOP加载顺序(切面加载顺序) 2.配置类加载顺序