题意:
Alan Alan 在玩骰子游戏, Alan Alan 会玩 n n 轮骰子,每轮的数值在 中随机出现。记 ai a i 表示 n n 轮投掷中,数值 出现的次数,求 aF1∗aF2∗...∗aFL a 1 F ∗ a 2 F ∗ . . . ∗ a L F 的期望。答案对 2003 2003 取模。
题解:
记
xi,j
x
i
,
j
表示第
i
i
轮结果是否为,那么:
展开多项式,考虑每个单项式的期望的和。 对于一个特定的单项式 ,是在每一个括号里面取 F F 项乘起来得到的,所以共有 项 ,我们把从第 i i 个括号中取的第个数 xb,i x b , i 的 b b 放入中,就得到了一个大小为 F∗L F ∗ L 的 A A 矩阵。所以每个单项式唯一对应一个矩阵。
对于一个特定的 A A 矩阵,如果,那么这个单项式的期望为0,因为一轮骰子不可能出现两个数。
否则这个单项式的期望为
1Kt
1
K
t
,
t
t
为的种类数。
枚举
t
t
, 问题变为了我们在的矩阵中填入
[1,n]
[
1
,
n
]
,且不同种类数为
t
t
的方案数。
按行考虑,我们先不考虑颜色种类和彼此的顺序,最后乘上即可,设
dpi,j
d
p
i
,
j
表示一行第
i
i
位出现种数的方案数,则有
dpi,j=dpi−1,j−1+dpi−1,j∗j
d
p
i
,
j
=
d
p
i
−
1
,
j
−
1
+
d
p
i
−
1
,
j
∗
j
。
最后倍增做
L
L
次背包(多项式乘法),然后枚举第几项即可。 注意对取模,后面的项因为要乘
t!
t
!
被消掉的,所以只需要存
2003
2003
位。
时间复杂度: O(F2+20032logL) O ( F 2 + 2003 2 log L )
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e3+50, mod=2003;
inline int add(int x,int y) {return (x+y>=mod) ? (x+y-mod) : (x+y);}
inline int dec(int x,int y) {return (x-y<0) ? (x-y+mod) : (x-y);}
inline int mul(int x,int y) {return (LL)x*y%mod;}
inline int power(int a,int b,int rs=1) {for(;b;b>>=1,a=mul(a,a)) if(b&1) rs=mul(rs,a); return rs;}
int n,K,L,F;
int fac[mod],dn[mod],dp[N][N],G[mod],f[mod],ipw[mod];
inline void mul(int *a,int *b,int *c) {
static int tp[mod],tp2[mod];
for(int i=0;i<mod;i++) tp[i]=a[i], tp2[i]=b[i], c[i]=0;
for(int i=0;i<mod;i++)
for(int j=0;j<=i;j++)
c[i]=add(c[i],mul(tp[j],tp2[i-j]));
}
int main() {
cin>>n>>K>>L>>F;
const int invk=power(K,mod-2);
ipw[0]=fac[0]=dn[0]=1;
for(int i=1;i<mod;i++) ipw[i]=mul(ipw[i-1],invk), fac[i]=mul(fac[i-1],i);
for(int i=1;i<mod;i++) dn[i]=mul(dn[i-1],n-i+1);
dp[0][0]=1;
for(int i=1;i<=F;i++)
for(int j=1;j<=i;j++)
dp[i][j]=add(mul(dp[i-1][j],j),dp[i-1][j-1]);
for(int i=1;i<=F;i++) G[i]=dp[F][i];
f[0]=1;
for(int b=L;b;b>>=1,mul(G,G,G))
if(b&1) mul(f,G,f);
int ans=0;
for(int i=1;i<mod && i<=n;i++)
ans=add(ans,mul(dn[i],mul(ipw[i],f[i])));
cout<<ans;
}