Description
Math teacher is gone, English teacher is coming to class
His personality is different, and because everyone is a student of science class
He hopes that everyone can understand the joy of English in the process of number
letters He arranges them with m letters Combining,
get all the different strings of length n
(not all letters need to appear in the string)
For each string s
Define C(s) as the most frequent letter in s The number of occurrences
Then the question comes
All these character sets of size m, length n strings How many are
C(s)=k?
Input
A line of three integers n, m, k, representing length, character set and required C(s) respectively
Output
Output a line to represent
the result The answer is modulo 998244353
Sample Input
3 2 2
Sample Output
6
HINT
Data guarantee k≤n
For 10% of the data, 1≤n,m≤8
For 30% of the data, 1≤n,m≤200
For 50% of the data, 1≤n,m≤1000
For 100% data, 1≤n,m≤50000
Example explanation:
Suppose the two letters in the example are a, b
Then there are six aab, aba, abb, baa, bab, bba that meet the conditions
Solution
First, the most intuitive DP equations are listed.
Note that \(f[i][j][k]\) is currently considering the \(i\) th letter, the \(j\) position in the string has been used, and the number of occurrences of the most letters does not exceed \ (k\) the number of options. The answer is \(f[m][n][k]-f[m][n][k-1]\) .
The transition equation is obviously to enumerate how many times the current letter is used:
\[ f[i][j][k]=\sum_{x=0}^k {j\choose x}f[i-1][jx] [k] \]
Then you can find that \(k\) is very redundant and does not participate in the transfer. That is to say , \(k\) only acts on the loop range control.
We try to omit the last dimension: \(f[i][j]\) . \(k\) still works, that is, the current \(f[i][j]\) corresponds to the original \(f[i][j][k]\) .
Now look at the equation:
\[ \begin{aligned} f[i][j]&=\sum_{x=0}^k{j\choose x}f[i-1][jx]\\ &=\sum_{x=0 }^k\frac{j!}{x!(jx)!}f[i-1][jx]\\ \frac{f[i][j]}{j!}&=\sum_{x= 0}^k\;x!\;\frac{f[i-1][jx]}{(jx)!} \end{aligned} \]
is obviously a form of convolution, and the left side of the equal sign The form is the same as that of the right half of the convolution . So each \(f[i]\) can be regarded as a polynomial
\[ 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 \
] The transition is this polynomial sum
\[ T(x)=\frac1{0!}+\frac1{1!}x+\frac1{2!}x^2...+\frac1{k!}x^k \]
's convolution. That is, \(f[n]=f[0]*T^{n}(x)\)
and \(T(x)\) is independent and not affected by other things, so \(T(x )\) Convolve it with a fast power, and then convolve it with \(f[0]\) . According to the definition, \(f[0]=1\) , so it is equivalent to directly find \(T(x)\ )\(n\) power. Don't forget to multiply the answer by the factorial of \(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;
}