Description

  

​   数学老师走啦,英语老师来上课啦

  ​ 他的性格与众不同,又因为大家都是理科班的学生

  ​ 他希望大家在数字母的过程中领悟英语的快乐

​   他用m种字母进行排列组合,

​   得到了所有不同的,长度为n的字符串

​   (不需要所有字母都出现在字符串中)

  ​ 对于每个字符串s

​   定义C(s)为s中出现次数最多的字母的出现次数

​   那么问题来了

​   所有的这些字符集大小为m,长度为n的字符串中

​   C(s)=k的有多少个呢

  

Input

  

​   一行三个整数n,m,k,分别表示长度,字符集和要求的C(s)

  

Output

  

​   输出一行表示结果

​   答案对998244353取模

  

Sample Input

  

​   3 2 2

  

Sample Output

  

​   6

  

HINT

  

​   数据保证k≤n

​   对于10%的数据,1≤n,m≤8

​   对于30%的数据,1≤n,m≤200

​   对于50%的数据,1≤n,m≤1000

​   对于100%的数据,1≤n,m≤50000

  

​   样例解释:

  

​   假设样例中的两个字母为a,b

​   则满足条件的有aab,aba,abb,baa,bab,bba六个

    

  

  

Solution

  

​   首先把最直观的DP方程列出来。

  

  记\(f[i][j][k]\)为当前考虑到第\(i\)个字母,已经使用了串中的\(j\)个位置,出现最多的字母次数不超过\(k\)的方案数。答案就是\(f[m][n][k]-f[m][n][k-1]\)。

   

​   转移方程显然是枚举当前字母使用多少次:

\[f[i][j][k]=\sum_{x=0}^k {j\choose x}f[i-1][j-x][k]
\]

  ​ 然后可以发现\(k\)十分的冗余,并没有参与转移。也就是说\(k\)仅仅作用于循环范围控制上。

  

​   我们尝试把最后一维省掉:\(f[i][j]\)。\(k\)仍然发挥作用,也就是现在的\(f[i][j]\)对应着原来的\(f[i][j][k]\)。

  

  ​ 现在看看方程:

\[\begin{aligned}
f[i][j]&=\sum_{x=0}^k{j\choose x}f[i-1][j-x]\\
&=\sum_{x=0}^k\frac{j!}{x!(j-x)!}f[i-1][j-x]\\
\frac{f[i][j]}{j!}&=\sum_{x=0}^k\;x!\;\frac{f[i-1][j-x]}{(j-x)!}
\end{aligned}
\]

​   后面显然是一个卷积的形式,并且等号左边的形式和卷积右半边的形式一样。所以可以把每个\(f[i]\)看做一个多项式

  

\[f[i]=\frac{f[i][0]}{0!}+\frac{f[i][1]}{1!}x+\frac{f[i][2]}{2!}x^2+...+\frac{f[i][n]}{n!}x^n
\]

  

​   转移就是这个多项式和

  

\[T(x)=\frac1{0!}+\frac1{1!}x+\frac1{2!}x^2...+\frac1{k!}x^k
\]

  

  ​ 的卷积。即\(f[n]=f[0]*T^{n}(x)\)

  

​   而\(T(x)\)是独立的存在不受其他东西影响,所以将\(T(x)\)用快速幂自卷积一下,再用\(f[0]\)卷积一下就好了。根据定义,\(f[0]=1\),所以相当于直接求\(T(x)\)的\(n\)次方。答案别忘了乘上\(n\)的阶乘。

  

  1. #include <cstdio>
  2. #include <cstring>
  3. using namespace std;
  4. const int N=50005,MOD=998244353,G=3,B17=131100;
  5. int fact[N],iact[N];
  6. inline void swap(int &x,int &y){x^=y^=x^=y;}
  7. inline int pow(int x,int y){
  8. int res=1;
  9. for(;y;x=1LL*x*x%MOD,y>>=1)
  10. if(y&1) res=1LL*res*x%MOD;
  11. return res;
  12. }
  13. namespace NTT{/*{{{*/
  14. int n,invn,bit,rev[B17],W[B17][2];
  15. void build(){
  16. int b=pow(G,MOD-2);
  17. for(int i=0;i<=17;i++){
  18. W[1<<i][0]=pow(G,(MOD-1)/(1<<i));
  19. W[1<<i][1]=pow(b,(MOD-1)/(1<<i));
  20. }
  21. }
  22. void init(int _n){
  23. for(n=1,bit=0;n<_n;n<<=1,bit++);
  24. invn=pow(n,MOD-2);
  25. for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
  26. }
  27. void clear(int *a){for(int i=0;i<n;i++)a[i]=0;}
  28. void ntt(int *a,int f){
  29. for(int i=0;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
  30. int u,v,w_n,w;
  31. for(int i=2;i<=n;i<<=1){
  32. w_n=W[i][f==-1];
  33. for(int j=0;j<n;j+=i){
  34. w=1;
  35. for(int k=0;k<i/2;k++){
  36. u=a[j+k]; v=1LL*w*a[j+i/2+k]%MOD;
  37. a[j+k]=(u+v)%MOD; a[j+i/2+k]=(u-v)%MOD;
  38. w=1LL*w*w_n%MOD;
  39. }
  40. }
  41. }
  42. if(f==-1)
  43. for(int i=0;i<n;i++) a[i]=1LL*a[i]*invn%MOD;
  44. }
  45. }/*}}}*/
  46. void ksm(int *x,int y,int n,int *res){
  47. NTT::init((n+1)*2);
  48. NTT::clear(res);
  49. res[0]=1;
  50. for(;y;y>>=1){
  51. NTT::ntt(x,1);
  52. if(y&1){
  53. NTT::ntt(res,1);
  54. for(int i=0;i<NTT::n;i++) res[i]=1LL*res[i]*x[i]%MOD;
  55. NTT::ntt(res,-1);
  56. for(int i=n+1;i<NTT::n;i++) res[i]=0;
  57. }
  58. for(int i=0;i<NTT::n;i++) x[i]=1LL*x[i]*x[i]%MOD;
  59. NTT::ntt(x,-1);
  60. for(int i=n+1;i<NTT::n;i++) x[i]=0;
  61. }
  62. }
  63. int solve(int n,int m,int k){
  64. static int a[B17],b[B17];
  65. memset(a,0,sizeof a);
  66. for(int i=0;i<=k;i++) a[i]=iact[i];
  67. ksm(a,m,n,b);
  68. return 1LL*fact[n]*b[n]%MOD;
  69. }
  70. int main(){
  71. freopen("input.in","r",stdin);
  72. NTT::build();
  73. int n,m,k;
  74. scanf("%d%d%d",&n,&m,&k);
  75. fact[0]=1;
  76. for(int i=1;i<=n;i++) fact[i]=1LL*fact[i-1]*i%MOD;
  77. iact[n]=pow(fact[n],MOD-2);
  78. for(int i=n-1;i>=0;i--) iact[i]=1LL*iact[i+1]*(i+1)%MOD;
  79. int ans=(solve(n,m,k)-solve(n,m,k-1))%MOD;
  80. printf("%d\n",ans<0?ans+MOD:ans);
  81. return 0;
  82. }

Counting的更多相关文章

  1. 萌新笔记——Cardinality Estimation算法学习(二)(Linear Counting算法、最大似然估计(MLE))

    在上篇,我了解了基数的基本概念,现在进入Linear Counting算法的学习. 理解颇浅,还请大神指点! http://blog.codinglabs.org/articles/algorithm ...

  2. POJ_2386 Lake Counting (dfs 错了一个负号找了一上午)

    来之不易的2017第一发ac http://poj.org/problem?id=2386 Lake Counting Time Limit: 1000MS   Memory Limit: 65536 ...

  3. ZOJ3944 People Counting ZOJ3939 The Lucky Week (模拟)

    ZOJ3944 People Counting ZOJ3939 The Lucky Week 1.PeopleConting 题意:照片上有很多个人,用矩阵里的字符表示.一个人如下: .O. /|\ ...

  4. find out the neighbouring max D_value by counting sort in stack

    #include <stdio.h> #include <malloc.h> #define MAX_STACK 10 ; // define the node of stac ...

  5. 1004. Counting Leaves (30)

    1004. Counting Leaves (30)   A family hierarchy is usually presented by a pedigree tree. Your job is ...

  6. 6.Counting Point Mutations

    Problem Figure 2. The Hamming distance between these two strings is 7. Mismatched symbols are colore ...

  7. 1.Counting DNA Nucleotides

    Problem A string is simply an ordered collection of symbols selected from some alphabet and formed i ...

  8. uva 11401 Triangle Counting

    // uva 11401 Triangle Counting // // 题目大意: // // 求n范围内,任意选三个不同的数,能组成三角形的个数 // // 解题方法: // // 我们设三角巷的 ...

  9. JSONKit does not support Objective-C Automatic Reference Counting(ARC) / ARC forbids Objective-C objects in struct

    当我们在使用JSONKit处理数据时,直接将文件拉进项目往往会报这两个错“JSONKit   does not support Objective-C Automatic Reference Coun ...

  10. iOS开发 JSonKit does not support Objective-C Automatic Reference Counting(ARC)

    有使用JSonKit的朋友,如果遇到“JSonKit does not support Objective-C Automatic Reference Counting(ARC)”这种情况,可参照如下 ...

随机推荐

  1. 【SIKIA计划】_05_Unity5.3开发2D游戏笔记

    一.界面基本操作 01.Project基本分类[Audios]音效[Material]材质[Prefabs]预制[Scenes]场景[Scripts]脚本[Sprites]精灵 02.Project丶 ...

  2. 解决java读取大文件内存溢出问题

    1. 传统方式:在内存中读取文件内容 读取文件行的标准方式是在内存中读取,Guava 和Apache Commons IO都提供了如下所示快速读取文件行的方法: Files.readLines(new ...

  3. NO--19 微信小程序之scroll-view选项卡与跳转(二)

    本篇为大家介绍为何我们在最后做交互的时候,并没有使用上一篇讲的选项卡的效果.   scroll-view与跳转.gif (如无法查看图片,还请翻看上一篇!) 大家注意看,在我点击跳转后,首先能看到的是 ...

  4. 【LeetCode算法题库】Day1:TwoSums & Add Two Numbers & Longest Substring Without Repeating Characters

    [Q1] Given an array of integers, return indices of the two numbers such that they add up to a specif ...

  5. 0.3 CMD常用命令!以及用CMD显得自己高大上

    CMD是大家熟知的Windows命令提示符(cmd.exe),它是 Windows NT 下的一个用于运行 Windows 控制面板程序或某些 DOS 程序的shell程序. CMD命令快捷键是:wi ...

  6. 解析xml报文,xml与map互转

    这段时间写了一个关于xml报文的工具类,做一下具体的讲解: xml文本 <NTMMessage version="1.03"> <NTMHeader> &l ...

  7. ngxin 添加模块

    if test -n "$NGX_ADDONS"; then echo configuring additional modules for ngx_addon_dir in $N ...

  8. Java 的 java_home, path, classpath

    java_home: 指定 jdk 的安装目录. 第三方软件 Eclipse / Tomcat 在 java_home 指定的目录下查找安装好的 jdk. path: 配置 jdk 的安装目录.在命令 ...

  9. centos7安装oracle的一些问题

    在配置监听的时候尝试了很多次都是不能创建,最后将 /data/oracle/product/11.2.0/db_1/network/admin目录下的listener.ora和tnsname.ora两 ...

  10. AloneQIan---第一次作业

    小学生的噩梦 一.估计与实际 PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划 600 720 • Estim ...