NaCly_Fish
2020-01-29 03:13:18
在我的博客内看体验更佳(
updated:改为
ps:这个复杂度的做法 iostream 比我先做出来。
设
后面那个
考虑化简后面那个式子
然后直接得到原式为
这样就可以
暴力拆开原式的 Stirling 数得到
根据组合数的基本意义可以化为
后面一个和式改为枚举从
设后面那个和式为
做个差分,再做一些麻烦的推式子,就能得到如下关系:
(我的推法又臭又长,而且也没什么技术含量,就不放上来了)
用线性筛求出
要注意的是
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 10000003
#define ll long long
#define p 998244353
#define reg register
using namespace std;
inline int power(int a,int t){
int res = 1;
while(t){
if(t&1) res = (ll)res*a%p;
a = (ll)a*a%p;
t >>= 1;
}
return res;
}
int n,m,k,cnt;
int f[N],inv[N],pw[N],pr[N>>1],c[N];
int solve1(){
int mul = (ll)power(p+1-m,n-1)*m%p,invq = power(p+1-m,p-2),res = 0;
for(reg int i=1;i<=n;++i){
res = (res+(ll)mul*c[i]%p*pw[i])%p;
mul = (ll)mul*invq%p*m%p;
}
return res;
}
int solve2(){
int c2,mul,res = 0;
mul = c2 = f[k] = 1;
for(reg int i=k-1;i;--i){
c2 = (ll)c2*(n-i-1)%p*inv[k-i]%p;
mul = (ll)mul*(p-m)%p;
f[i] = ((ll)c2*mul+(ll)(p+1-m)*f[i+1])%p;
}
mul = m;
for(reg int i=1;i<=k;++i){
res = (res+(ll)pw[i]*c[i]%p*mul%p*f[i])%p;
mul = (ll)mul*m%p;
}
return res;
}
int main(){
scanf("%d%d%d",&n,&m,&k);
m = power(m,p-2);
c[0] = inv[1] = pw[1] = 1;
c[1] = n;
for(reg int i=2;i<=k;++i){
inv[i] = (ll)(p-p/i)*inv[p%i]%p;
c[i] = (ll)c[i-1]*inv[i]%p*(n-i+1)%p;
if(!pw[i]){
pr[++cnt] = i;
pw[i] = power(i,k);
}
for(reg int j=1;j<=cnt&&(ll)i*pr[j]<=k;++j){
pw[i*pr[j]] = (ll)pw[i]*pw[pr[j]]%p;
if(i%pr[j]==0) break;
}
}
if(n<=k+1) printf("%d",solve1());
else printf("%d",solve2());
return 0;
}