题解 P6031【Cards 加强版】
学习一下斯特林相关技巧,这是一道基础练习题。
题意
有 $m$ 张牌,其中一张为特殊牌,其余为相同的普通牌。将牌均匀打乱 $n$ 次,如果有 $x$ 次特殊牌在第一位,则得分为 $x^k$,求 $E(x^k)$ 对 $998244353$ 取模的结果。
$1\le k\le 10^7$,$1\le n,m<\bmod$。
思路
写出式子。
$$\sum_{i=0}^n\binom{n}{i}p^{i}(1-p)^{n-i}i^k$$
其中 $p=\dfrac 1 m$。
展开普通幂。
$$\sum_{i=0}^n\binom{n}{i}p^{i}(1-p)^{n-i}\sum_{j=0}^k{k\brace j}i^{\underline{j}}$$
交换求和顺序。
$$\sum_{j=0}^k{k\brace j}\sum_{i=0}^n\binom{n}{i}i^{\underline{j}}p^{i}(1-p)^{n-i}$$
$$\sum_{j=0}^k{k\brace j}n^{\underline{j}}\sum_{i=0}^n\binom{n-j}{i-j}p^{i}(1-p)^{n-i}$$
用 $i-j$ 替换 $i$。
$$\sum_{j=0}^k{k\brace j}n^{\underline{j}}\sum_{i=0}^{n-j}\binom{n-j}{i}p^{i+j}(1-p)^{n-i-j}$$
$$\sum_{j=0}^k{k\brace j}n^{\underline{j}}p^j\sum_{i=0}^{n-j}\binom{n-j}{i}p^{i}(1-p)^{n-i-j}$$
二项式定理。
$$\sum_{j=0}^k{k\brace j}n^{\underline{j}}p^j$$
此时复杂度只能做到 $O(k\log k)$ 无法通过。
第二类斯特林数通项公式。
$${n\brace m}=\dfrac{1}{m!}\sum_{i=0}^m (-1)^{m-i}\binom mii^n$$
$$\sum_{i=0}^k\dfrac{n^{\underline{i}}p^i}{i!}\sum_{j=0}^i(-1)^{i-j}\binom{i}{j}j^k$$
交换求和顺序。
$$\sum_{j=0}^k(-1)^{j}j^k\sum_{i=j}^k\dfrac{n^{\underline{i}}(-p)^i}{i!}\binom{i}{j}$$
展开组合数。
$$\sum_{j=0}^k\dfrac{(-1)^{j}j^k}{j!}\sum_{i=j}^k\dfrac{n^{\underline{i}}(-p)^i}{(i-j)!}$$
用 $i-j$ 替换 $i$。
$$\sum_{j=0}^k\dfrac{(-1)^{j}j^k(-p)^j}{j!}\sum_{i=0}^{k-j}\dfrac{n^{\underline{i+j}}(-p)^i}{i!}$$
$$\sum_{j=0}^k\dfrac{j^kp^jn^{\underline{j}}}{j!}\sum_{i=0}^{k-j}\dfrac{(n-j)^{\underline{i}}(-p)^i}{i!}$$
$$\sum_{j=0}^k\dfrac{j^kp^jn^{\underline{j}}}{j!}\sum_{i=0}^{k-j}\binom{n-j}{i}(-p)^i$$
下文 $p$ 等于原来的 $-p$。
记:$$f(j)=\sum_{i=0}^{k-j}\binom{n-j}{i}p^i$$
$$\begin{aligned}f(j-1)-f(j) &=\sum_{i=0}^{k-j+1}\binom{n-j+1}{i}p^i-\sum_{i=0}^{k-j}\binom{n-j}{i}p^i\\ &=\sum_{i=0}^{k-j}p^i\left[\binom{n-j+1}{i}-\binom{n-j}{i}\right]+\binom{n-j+1}{k-j+1}p^{k-j+1}\\ &=\sum_{i=0}^{k-j}\binom{n-j}{i-1}p^i+\binom{n-j+1}{k-j+1}p^{k-j+1}\\ &=p\sum_{i=0}^{k-j-1}\binom{n-j}{i}p^i+\binom{n-j+1}{k-j+1}p^{k-j+1}\\ &=p\left[f(j)-\binom{n-j}{k-j}p^{k-j}\right]+\binom{n-j+1}{k-j+1}p^{k-j+1}\\ &=pf(j)+\left[\binom{n-j+1}{k-j+1}-\binom{n-j}{k-j}\right]p^{k-j+1}\\ &=pf(j)+\binom{n-j}{k-j+1}p^{k-j+1} \end{aligned}$$
所以,
$$\begin{aligned}f(j-1)&=(p+1)f(j)+\binom{n-j}{k-j+1}p^{k-j+1}\\ &=(p+1)f(j)+\dfrac{(n-j)^{\underline{k-j+1}}}{(k-j+1)!}p^{k-j+1}\\ &=(p+1)f(j)+\dfrac{n^{\underline{k+1}}}{n^{\underline{j}}(k-j+1)!}p^{k-j+1} \end{aligned}$$
边界是:
$$f(\min(n,k))=1$$
注意 $p$ 符号变了。
$$\sum_{j=0}^k\dfrac{j^k(-p)^jn^{\underline{j}}}{j!}f(j)$$
递推求出 $f(j)$,时间复杂度 $O(k)$。
预处理 $i^k$,$p^i$,$\dfrac{1}{i!}$,$n^{\underline{i}}$,$\dfrac 1 {n^{\underline{i}}}$ 即可。注意一下空间。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
namespace IO{//by cyffff
}
const int N=1e7+10,mod=998244353;
int n,m,k,p,q,f[N],ifac[N],dw[N],idw[N],pwk[N],pwp[N];
int cnt,pri[N/10];
bool vis[N];
inline int qpow(int x,int y){
int res=1;
while(y){
if(y&1) res=1ll*res*x%mod;
x=1ll*x*x%mod;
y>>=1;
}
return res;
}
inline void Prefix(int n){
f[1]=1,pwk[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]){
pri[++cnt]=i;
pwk[i]=qpow(i,k);
}
for(int j=1;j<=cnt&&i*pri[j]<=n;j++){
pwk[i*pri[j]]=1ll*pwk[i]*pwk[pri[j]]%mod;
vis[i*pri[j]]=1;
if(i%pri[j]==0) break;
}
}
ifac[0]=1;
for(int i=1;i<=n;i++)
ifac[i]=1ll*ifac[i-1]*i%mod;
ifac[n]=qpow(ifac[n],mod-2);
for(int i=n;i>=1;i--)
ifac[i-1]=1ll*ifac[i]*i%mod;
pwp[0]=1;
for(int i=1;i<=n;i++)
pwp[i]=1ll*pwp[i-1]*p%mod;
}
inline void Prefix2(int u){
dw[0]=1;
for(int i=1;i<=u;i++)
dw[i]=1ll*dw[i-1]*(n-i+1)%mod;
idw[u]=qpow(dw[u],mod-2);
for(int i=u;i>=1;i--)
idw[i-1]=1ll*idw[i]*(n-i+1)%mod;
}
int main(){
n=read(),m=read(),k=read();
p=qpow(m,mod-2),p=(mod-p)%mod;
Prefix(k+5),Prefix2(k+5);
f[min(k,n)]=1;
for(int i=min(k,n);i>=1;i--)
f[i-1]=(1ll*(p+1)*f[i]+1ll*dw[k+1]*idw[i]%mod*ifac[k-i+1]%mod*pwp[k-i+1])%mod;
int ans=0;
for(int i=0;i<=k;i++){
int tmp=1ll*pwk[i]*pwp[i]%mod*dw[i]%mod*ifac[i]%mod*f[i]%mod;
if(i&1) ans=(ans+mod-tmp)%mod;
else ans=(ans+tmp)%mod;
}
write(ans);
flush();
}

浙公网安备 33010602011771号