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\)的阶乘。

  

#include <cstdio>
#include <cstring>
using namespace std;
const int N=50005,MOD=998244353,G=3,B17=131100;
int fact[N],iact[N];
inline void swap(int &x,int &y){x^=y^=x^=y;}
inline int pow(int x,int y){
int res=1;
for(;y;x=1LL*x*x%MOD,y>>=1)
if(y&1) res=1LL*res*x%MOD;
return res;
}
namespace NTT{/*{{{*/
int n,invn,bit,rev[B17],W[B17][2];
void build(){
int b=pow(G,MOD-2);
for(int i=0;i<=17;i++){
W[1<<i][0]=pow(G,(MOD-1)/(1<<i));
W[1<<i][1]=pow(b,(MOD-1)/(1<<i));
}
}
void init(int _n){
for(n=1,bit=0;n<_n;n<<=1,bit++);
invn=pow(n,MOD-2);
for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(bit-1));
}
void clear(int *a){for(int i=0;i<n;i++)a[i]=0;}
void ntt(int *a,int f){
for(int i=0;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
int u,v,w_n,w;
for(int i=2;i<=n;i<<=1){
w_n=W[i][f==-1];
for(int j=0;j<n;j+=i){
w=1;
for(int k=0;k<i/2;k++){
u=a[j+k]; v=1LL*w*a[j+i/2+k]%MOD;
a[j+k]=(u+v)%MOD; a[j+i/2+k]=(u-v)%MOD;
w=1LL*w*w_n%MOD;
}
}
}
if(f==-1)
for(int i=0;i<n;i++) a[i]=1LL*a[i]*invn%MOD;
}
}/*}}}*/
void ksm(int *x,int y,int n,int *res){
NTT::init((n+1)*2);
NTT::clear(res);
res[0]=1;
for(;y;y>>=1){
NTT::ntt(x,1);
if(y&1){
NTT::ntt(res,1);
for(int i=0;i<NTT::n;i++) res[i]=1LL*res[i]*x[i]%MOD;
NTT::ntt(res,-1);
for(int i=n+1;i<NTT::n;i++) res[i]=0;
}
for(int i=0;i<NTT::n;i++) x[i]=1LL*x[i]*x[i]%MOD;
NTT::ntt(x,-1);
for(int i=n+1;i<NTT::n;i++) x[i]=0;
}
}
int solve(int n,int m,int k){
static int a[B17],b[B17];
memset(a,0,sizeof a);
for(int i=0;i<=k;i++) a[i]=iact[i];
ksm(a,m,n,b);
return 1LL*fact[n]*b[n]%MOD;
}
int main(){
freopen("input.in","r",stdin);
NTT::build();
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
fact[0]=1;
for(int i=1;i<=n;i++) fact[i]=1LL*fact[i-1]*i%MOD;
iact[n]=pow(fact[n],MOD-2);
for(int i=n-1;i>=0;i--) iact[i]=1LL*iact[i+1]*(i+1)%MOD;
int ans=(solve(n,m,k)-solve(n,m,k-1))%MOD;
printf("%d\n",ans<0?ans+MOD:ans);
return 0;
}

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. Netty源码分析第5章(ByteBuf)---->第10节: SocketChannel读取数据过程

    Netty源码分析第五章: ByteBuf 第十节: SocketChannel读取数据过程 我们第三章分析过客户端接入的流程, 这一小节带大家剖析客户端发送数据, Server读取数据的流程: 首先 ...

  2. 【树莓派】crontab的两个问题

    1,/var/log下面,没有cron.log日志 root@raspberrypi:/# nano /etc/rsyslog.conf …… …… ############### #### RULE ...

  3. sqli-labs学习笔记 DAY8

    DAY 8 sqli-lab Page-3 sqli-labs lesson 38 What is Stacked injection? https://blog.csdn.net/Fly_hps/a ...

  4. No.11_功能规格说明书

    功能规格说明书 • 基本目标 为用户提供更加便捷和人性化的闹钟提醒服务,以群组为单位规划时间安排与分配,对于个人用户,实现个人的设置闹钟,取消闹钟的操作,这些操作将会上传至数据库,并被同步到所有的客户 ...

  5. Task 6.2冲刺会议四 /2015-5-17

    今天主要是学习并熟悉了C#的开发流程,把他的文件的大体结构和每个组件之间的联系弄清楚之后.开始写服务器部分的内容.学习过程中,感觉网上的资料有些太鱼龙混杂了,不知道该怎么取舍.明天准备完善服务器的功能 ...

  6. angularJS1笔记-(17)-ng-bind-html指令

    angular不推荐大家在绑定数据的时候绑定html,但是如果你非要这么干也并不是不可以的.举个例子: <!DOCTYPE html> <html lang="en&quo ...

  7. Redis有序集内部实现原理分析

    Redis技术交流群481804090 Redis:https://github.com/zwjlpeng/Redis_Deep_Read Redis中支持的数据结构比Memcached要多的多啦,如 ...

  8. TCP连接 三次握手 四次挥手

    前言: TCP协议是面向连接.安全可靠.基于字节流的传输层协议,在进行http协议访问时就用到了tcp连接.在建立TCP连接时需要经历三次握手,断开连接时需要经历四次挥手.在此进行记录. 内容: TC ...

  9. 关于mysqlbinlog的重要性.

    今天在做update更新数据的时候,因为没有统一好需要更新的数据编执行了update操作,所以需要回滚到先前的数据,所以就赶紧去服务器看binlog日志,结果一看binlog竟然没有开启,把我给惊的啊 ...

  10. Vue 爬坑之路(一)—— 使用 vue-cli 搭建项目 (增补)

    cd  指定好安装目录 vue init webpack  项目名称 执行  vue vue list  查看可应用模板 vue init webpack  +名字 项目已启动