首先我们考虑$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)$求解,因此能通过这题:

  1. // luogu-judger-enable-o2
  2. #include <cstdio>
  3. #include <cmath>
  4. #include <cstring>
  5. #include <algorithm>
  6. #define ll unsigned long long
  7. #define uint unsigned int
  8. using namespace std;
  9. const uint mode=998244353;
  10. uint pow_mul(uint x,uint y)
  11. {
  12. uint ret=1;
  13. while(y)
  14. {
  15. if(y&1)ret=1ll*ret*x%mode;
  16. x=1ll*x*x%mode,y>>=1;
  17. }
  18. return ret;
  19. }
  20. uint inv[300005],minv[300005],mul[300005];
  21. void init()
  22. {
  23. inv[0]=inv[1]=minv[0]=minv[1]=mul[0]=mul[1]=1;
  24. for(uint i=2;i<=300000;i++)
  25. {
  26. inv[i]=1ll*(mode-mode/i)*inv[mode%i]%mode;
  27. minv[i]=1ll*minv[i-1]*inv[i]%mode;
  28. mul[i]=1ll*mul[i-1]*i%mode;
  29. }
  30. }
  31. uint MOD(uint x,uint y)
  32. {
  33. return x+y>=mode?x+y-mode:x+y;
  34. }
  35. uint to[(1<<20)+5];
  36. uint n,a,b;
  37. void NTT(uint *a,uint len,int k)
  38. {
  39. for(uint i=0;i<len;i++)if(i<to[i])swap(a[i],a[to[i]]);
  40. for(uint i=1;i<len;i<<=1)
  41. {
  42. uint w0=pow_mul(3,(mode-1)/(i<<1));
  43. for(uint j=0;j<len;j+=(i<<1))
  44. {
  45. uint w=1;
  46. for(uint o=0;o<i;o++,w=1ll*w*w0%mode)
  47. {
  48. ll w1=a[j+o],w2=1ll*a[j+o+i]*w%mode;
  49. a[j+o]=MOD(w1,w2)%mode,a[j+o+i]=MOD(mode-w2,w1);
  50. }
  51. }
  52. }
  53. if(k==-1)
  54. {
  55. uint inv=pow_mul(len,mode-2);
  56. for(uint i=1;i<(len>>1);i++)swap(a[i],a[len-i]);
  57. for(uint i=0;i<len;i++)a[i]=1ll*a[i]*inv%mode;
  58. }
  59. }
  60. uint A[(1<<20)+5],B[(1<<20)+5],C[(1<<20)+5];
  61. uint tempt[(1<<20)+5],tempf[(1<<20)+5],tempg[(1<<20)+5],tempG[(1<<20)+5],tempF[(1<<20)+5];
  62. uint ret[(1<<20)+5];
  63. void mult(uint *f,uint *g,uint len)
  64. {
  65. uint lim=1,l=0;
  66. while(lim<=2*(len+1))lim<<=1,l++;
  67. for(uint i=0;i<lim;i++)to[i]=((to[i>>1]>>1)|((i&1)<<(l-1)));
  68. for(uint i=0;i<lim;i++)A[i]=B[i]=0;
  69. for(uint i=0;i<=len;i++)A[i]=f[i],B[i]=g[i];
  70. for(uint i=0;i<lim;i++)C[i]=0;
  71. NTT(A,lim,1),NTT(B,lim,1);
  72. for(uint i=0;i<lim;i++)C[i]=1ll*A[i]*B[i]%mode;
  73. NTT(C,lim,-1);
  74. }
  75. void solve(uint *g,uint dep)
  76. {
  77. if(!dep){g[0]=1;return;}
  78. if(dep==1)
  79. {
  80. g[0]=0,g[1]=1;
  81. return;
  82. }
  83. if(dep&1)
  84. {
  85. solve(g,dep-1);
  86. for(uint i=1;i<=dep;i++)tempG[i]=C[i-1];
  87. for(uint i=0;i<dep;i++)tempG[i]=MOD(tempG[i],1ll*C[i]*(dep-1)%mode);
  88. for(uint i=0;i<=dep;i++)g[i]=tempG[i];
  89. }else
  90. {
  91. uint mid=(dep>>1);
  92. solve(g,mid);
  93. uint temp=1;
  94. 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;
  95. mult(tempg,tempf,mid);
  96. for(uint i=0;i<=mid;i++)tempF[i]=1ll*C[mid-i]*minv[i]%mode;
  97. mult(tempF,g,mid);
  98. for(uint i=0;i<=dep;i++)g[i]=C[i];
  99. }
  100. }
  101. uint get_C(uint x,uint y)
  102. {
  103. if(x<y)return 0;
  104. return 1ll*mul[x]*minv[y]%mode*minv[x-y]%mode;
  105. }
  106. int main()
  107. {
  108. scanf("%u%u%u",&n,&a,&b);init();
  109. solve(ret,n-1);
  110. printf("%u\n",1ll*ret[a+b-2]*get_C(a+b-2,a-1)%mode);
  111. return 0;
  112. }

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. 使用Wireshark完成实验3-IP

    1.使用Wireshark打开ip-ethereal-trace-1,如图 电脑IP地址为192.168.1.102 2.如图,IP包头中上层协议字段的值为1,代表为ICMP 3.如图,IP头中有20 ...

  2. Java基础学习:8、构造器(构造方法)和this

    一.构造器: 1.定义:构造器是类的特殊方法,它的主要作用是完成对象的初始化.          即在创建对象时初始化对象.   本质是方法. 2.特点: a.方法名和类名一致. b.无返回值. c. ...

  3. GNSS模块

    1. Location服务注册 第一个注册是在 SystemServer 中将 location 服务注册到 ServiceManager中去:第二个注册是在 SystemServiceRegistr ...

  4. Linux环境下给python项目写个启停服务

    写个服务,写完后放在/lib/systemd/system路径下 update_rule.server [Unit] Description = TinyScan update rule [Servi ...

  5. 5.mysql的explain的分析

    执行分析:  1.id 含义:表示查询的子句或者操作表的顺序 三种情况:id 相同,执行的顺序由上到下: id不同,id越大优先级越高,越先执行: id相同不相同同时存在: 2.select_type ...

  6. Django-django-celery的配置

    1.安装django-celery   pip install django-celery 2.添加配置 demos/demos/settings.py(我的项目名为demos,这里只是示范,切勿搞混 ...

  7. Java调用Kettle

    Java 调用 kettle,难的不是怎么调用,而是解决 maven 依赖冲突问题,直接将 kettle 依赖,添加到我们的 maven 工程,可能会导致代码大范围报错:解决方案也很简单,就是直接从 ...

  8. 国际版Office365客户端配置

    Email Provider IMAP Settings POP Settings SMTP Settings Microsoft 365 Outlook Hotmail Live.com Serve ...

  9. EasyUI异步Tree默认请求id获取不到问题

    在做淘淘商城项目过程中,在新增商品-选择类目时,使用EasyUI的异步Tree功能,根据视频教程封装了一个common pojo--EUTreeNode对象,属性值取parentId(id).text ...

  10. js中常用的运算符

    1. ?. 链接运算符 特性: 一旦遇到空置就会终止 例子: let name = obj?.name persion.getTip?.() // 没有getTip 方法则不会执行 2. ?? 空值合 ...