题目大意:在字符集大小为$m$的情况下,有多少种构造长度为$n$的字符串$s$的方案,使得$C(s)=k$。其中$C(s)$表示字符串$s$中出现次数最多的字符的出现次数。

对$998244353$取模,$n,m≤5\times 10^4$

如果你考虑去DP,你就lose了。

令$F(x)$表示满足$C(s)≤x$的方案数。

那么最终的答案显然为$F(k)-F(k-1)$。

这一题有一个非常优美的性质:对于每一种字符,允许的最多出现次数都是$k$。

那么,令$G_k(x)=\sum\limits_{i=0}^{k} \frac{1}{i!}x^i$

则有$F(k)=n![x^n]G_k^m(x)$

证明是显然的

写一个多项式快速幂的板子就过了。

  1. #include<bits/stdc++.h>
  2. #define M (1<<17)
  3. #define L long long
  4. #define MOD 998244353
  5. #define G 3
  6. using namespace std;
  7.  
  8. L pow_mod(L x,L k){
  9. L ans=;
  10. while(k){
  11. if(k&) ans=ans*x%MOD;
  12. x=x*x%MOD; k>>=;
  13. }
  14. return ans;
  15. }
  16.  
  17. void change(L a[],int n){
  18. for(int i=,j=;i<n-;i++){
  19. if(i<j) swap(a[i],a[j]);
  20. int k=n>>;
  21. while(j>=k) j-=k,k>>=;
  22. j+=k;
  23. }
  24. }
  25. void NTT(L a[],int n,int on){
  26. change(a,n);
  27. for(int h=;h<=n;h<<=){
  28. L wn=pow_mod(G,(MOD-)/h);
  29. for(int j=;j<n;j+=h){
  30. L w=;
  31. for(int k=j;k<j+(h>>);k++){
  32. L u=a[k],t=w*a[k+(h>>)]%MOD;
  33. a[k]=(u+t)%MOD;
  34. a[k+(h>>)]=(u-t+MOD)%MOD;
  35. w=w*wn%MOD;
  36. }
  37. }
  38. }
  39. if(on==-){
  40. L inv=pow_mod(n,MOD-);
  41. for(int i=;i<n;i++) a[i]=a[i]*inv%MOD;
  42. reverse(a+,a+n);
  43. }
  44. }
  45.  
  46. void getinv(L a[],L b[],int n){
  47. if(n==){b[]=pow_mod(a[],MOD-); return;}
  48. static L c[M],d[M];
  49. memset(c,,n<<); memset(d,,n<<);
  50. getinv(a,c,n>>);
  51. for(int i=;i<n;i++) d[i]=a[i];
  52. NTT(d,n<<,); NTT(c,n<<,);
  53. for(int i=;i<(n<<);i++) b[i]=(*c[i]-d[i]*c[i]%MOD*c[i]%MOD+MOD)%MOD;
  54. NTT(b,n<<,-);
  55. for(int i=;i<n;i++) b[n+i]=;
  56. }
  57.  
  58. void qiudao(L a[],L b[],int n){
  59. memset(b,,sizeof(b));
  60. for(int i=;i<n;i++) b[i-]=i*a[i]%MOD;
  61. }
  62. void jifen(L a[],L b[],int n){
  63. memset(b,,sizeof(b));
  64. for(int i=;i<n;i++) b[i+]=a[i]*pow_mod(i+,MOD-)%MOD;
  65. }
  66.  
  67. void getln(L a[],L b[],int n){
  68. static L c[M],d[M];
  69. memset(c,,n<<); memset(d,,n<<);
  70. qiudao(a,c,n); getinv(a,d,n);
  71. NTT(c,n<<,); NTT(d,n<<,);
  72. for(int i=;i<(n<<);i++) c[i]=c[i]*d[i]%MOD;
  73. NTT(c,n<<,-);
  74. jifen(c,b,n);
  75. }
  76.  
  77. void getexp(L a[],L b[],int n){
  78. if(n==){b[]=; return;}
  79. static L lnb[M]; memset(lnb,,n<<);
  80. getexp(a,b,n>>); getln(b,lnb,n);
  81. for(int i=;i<n;i++) lnb[i]=(a[i]-lnb[i]+MOD)%MOD,b[i+n]=;
  82. lnb[n]=;
  83. lnb[]=(lnb[]+)%MOD;
  84. NTT(lnb,n<<,); NTT(b,n<<,);
  85. for(int i=;i<(n<<);i++) b[i]=b[i]*lnb[i]%MOD;
  86. NTT(b,n<<,-);
  87. for(int i=;i<n;i++) b[i+n]=;
  88. }
  89.  
  90. L a[M]={},b[M]={};
  91. L fac[M]={},invfac[M]={};
  92. int n,k,m;
  93.  
  94. L solve(){
  95. memset(a,,sizeof(a));
  96. memset(b,,sizeof(b));
  97. int nn=; while(nn<=n) nn<<=;
  98. for(int i=;i<=m;i++) a[i]=invfac[i];
  99. L hh=a[],invhh=pow_mod(hh,MOD-);
  100. for(int i=;i<nn;i++) a[i]=a[i]*invhh%MOD;
  101. getln(a,b,nn);
  102. for(int i=;i<nn;i++) b[i]=b[i]*k%MOD;
  103. getexp(b,a,nn);
  104. hh=pow_mod(hh,k);
  105. for(int i=;i<nn;i++) a[i]=a[i]*hh%MOD;
  106. return a[n];
  107. }
  108.  
  109. int main(){
  110. scanf("%d%d%d",&n,&k,&m);
  111. fac[]=; for(int i=;i<M;i++) fac[i]=fac[i-]*i%MOD;
  112. invfac[M-]=pow_mod(fac[M-],MOD-);
  113. for(int i=M-;~i;i--) invfac[i]=invfac[i+]*(i+)%MOD;
  114. L res1=solve();
  115. m--;
  116. L res2=solve();
  117. cout<<(res1-res2+MOD)*fac[n]%MOD<<endl;
  118. }

【xsy2479】counting 生成函数+多项式快速幂的更多相关文章

  1. 【bzoj3684】 大朋友和多叉树 生成函数+多项式快速幂+拉格朗日反演

    这题一看就觉得是生成函数的题... 我们不妨去推下此题的生成函数,设生成函数为$F(x)$,则$[x^s]F(x)$即为答案. 根据题意,我们得到 $F(x)=x+\sum_{i∈D} F^i(x)$ ...

  2. BZOJ3992 [SDOI2015]序列统计 【生成函数 + 多项式快速幂】

    题目 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数 列,数列中的每个数都属于集合S.小C用这个生成器生成了许多这样的数列.但是小C有一个问题 ...

  3. AtCoder AGC019E Shuffle and Swap (DP、FFT、多项式求逆、多项式快速幂)

    题目链接 https://atcoder.jp/contests/agc019/tasks/agc019_e 题解 tourist的神仙E题啊做不来做不来--这题我好像想歪了啊= =-- 首先我们可以 ...

  4. [SDOI2015]序列统计(多项式快速幂)

    题目描述 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S.小C用这个生成器生成了许多这样的数列.但是小C有一个问 ...

  5. BZOJ3645: Maze(FFT多项式快速幂)

    Description 众维拉先后在中土大陆上创造了精灵.人类以及矮人,其中矮人是生性喜好常年居住在地下的洞穴的存在,他们挖掘矿物甚至宝石,甚至用他们的勤劳勇敢智慧在地底下创造出了辉煌宏大的宫殿,错综 ...

  6. luoguP5219 无聊的水题 I 多项式快速幂

    有一个幼儿园容斥:最大次数恰好为 $m=$  最大次数最多为 $m$ - 最大次数最多为 $m-1$. 然后来一个多项式快速幂就好了. code: #include <cmath> #in ...

  7. 2018.12.31 bzoj3992: [SDOI2015]序列统计(生成函数+ntt+快速幂)

    传送门 生成函数简单题. 题意:给出一个集合A={a1,a2,...as}A=\{a_1,a_2,...a_s\}A={a1​,a2​,...as​},所有数都在[0,m−1][0,m-1][0,m− ...

  8. 【BZOJ3992】[SDOI2015]序列统计 NTT+多项式快速幂

    [BZOJ3992][SDOI2015]序列统计 Description 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属 ...

  9. bzoj 3992: [SDOI2015]序列统计【原根+生成函数+NTT+快速幂】

    还是没有理解透原根--题目提示其实挺明显的,M是质数,然后1<=x<=M-1 这种计数就容易想到生成函数,但是生成函数是加法,而这里是乘法,所以要想办法变成加法 首先因为0和任何数乘都是0 ...

随机推荐

  1. 迭代器模块 itertools

    无限迭代器 itertools 包自带了三个可以无限迭代的迭代器.这意味着,当你使用他们时,你要知道你需要的到底是最终会停止的迭代器,还是需要无限地迭代下去. 这些无限迭代器在生成数字或者在长度未知的 ...

  2. Springboot08-项目单元测试(接口测试)

    Springboot08-项目单元测试(接口测试) 前言 1-本文重点在于源码层面,分析Springboot单元测试的使用,对于其中的注解.方法等,不会仔细分析: 2-本文项目实例相关配置:Java- ...

  3. Working days

    form FRM_GET_WORKING_DAYS TABLES pt_days CHANGING pv_duration. DATA:ls_xt001w TYPE t001w, lv_sdate T ...

  4. elementui上传文件

    <el-form-item label="上传附件"> <transition name="fade"> <el-upload r ...

  5. protobuff 编译注意事项

    把protoc.exe增加到环境变量path,这样方便运行protoc 生成C++代码  protoc -I=Proto文件路径 –cpp_out=指定输出.h和.cc的目录 Proto文件 具体参数 ...

  6. Python开发——数据类型【运算符】

    算数运算符 比较运算符 赋值运算符 逻辑运算符 成员运算符

  7. tomcat源码分析-初始化过程

    digester 说明: https://www.cnblogs.com/devilwind/p/8192304.html

  8. 设计模式 工厂模式 使用shared_ptr

    参考http://blog.csdn.net/calmreason/article/details/50903729 所有产品继承同一基本类 由工厂保存基类指针 产生各类产品 代码 // 002.cp ...

  9. UVA 2451 Brackets sequence

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=9 ...

  10. Activity 重载方法 onStart和onResume、onPause和onStop的区别

    Activity 重载方法 onStart和onResume.onPause和onStop的区别 首先了解Activity的四种状态 Running状态:一个新的Activity启动入栈后,它在屏幕最 ...