一个网站共有 n n n张图片,每张图片有权值 w i wi wi,每次访问时看到第 i i i张的概率为 w i ∑ j = 1 n w j \frac{wi}{\sum_{j=1}^n wj } ∑j=1nwjwi,其中 a i ai ai为 1 1 1表示 N a u u o Nauuo Nauuo喜欢这张图片,为 0 0 0表示不喜欢, N a u u o Nauuo Nauuo会访问 m m m次网站,每次如果看到的是喜欢的图片就令其权值 + 1 +1 +1,是不喜欢的就令其权值 − 1 -1 −1,问访问 m m m次后各图片权值的期望为多少
我们可以发现对每个
i
i
i单独枚举其情况时,其他图片的权值我只需要知道喜欢和不喜欢权值的总和就行,不需要知道具体那一个的权值,这样我们就能把所以权值分成三类:
一类是我当前
i
i
i的权值,一类是总的其他图片中我喜欢的权值和,一类是总的其他图片中我不喜欢的权值和。
首先我们预处理出所有初始权重
w
i
wi
wi的总和
s
u
m
sum
sum,所有我喜欢的图片的初始权重的总和
x
x
x,和所有我不喜欢的图片的初始权重的总和
y
y
y
我们用
d
p
[
i
]
[
j
]
[
k
]
[
q
]
dp[i][j][k][q]
dp[i][j][k][q]表示对于第
i
i
i张图片,当前一共访问了
j
j
j次,
k
k
k次访问的是我喜欢的图片,
q
q
q次是当前图片的概率,那么我们将图片
i
i
i按
a
[
i
]
a[i]
a[i]为
1
1
1和为
0
0
0分成两类:
a
[
i
]
a[i]
a[i]为
1
1
1:
1.当前遇到我喜欢的但不是第
i
i
i张图片:
d
p
[
i
]
[
j
]
[
k
]
[
q
]
+
=
d
p
[
i
]
[
j
−
1
]
[
k
−
1
]
[
q
]
∗
x
+
k
−
1
−
(
w
[
i
]
+
q
)
s
u
m
−
(
j
−
k
)
+
k
−
1
dp[i][j][k][q]+=dp[i][j-1][k-1][q]*\frac{x+k-1-(w[i]+q)}{sum-(j-k)+k-1}
dp[i][j][k][q]+=dp[i][j−1][k−1][q]∗sum−(j−k)+k−1x+k−1−(w[i]+q),
k
≥
1
k\geq1
k≥1
因为转移的状态
d
p
[
i
]
[
j
−
1
]
[
k
−
1
]
[
q
]
dp[i][j-1][k-1][q]
dp[i][j−1][k−1][q]中遇到喜欢的有
k
−
1
k-1
k−1次,所以遇到不喜欢的有
j
−
1
−
(
k
−
1
)
j-1-(k-1)
j−1−(k−1)次,所以经过这
j
j
j次后,当前总权值为
s
u
m
−
(
j
−
k
)
+
k
−
1
sum-(j-k)+k-1
sum−(j−k)+k−1,其中喜欢的权值增加了(k-1),不喜欢的减少了
j
−
1
−
(
k
−
1
)
j-1-(k-1)
j−1−(k−1),因为当前遇到了
q
q
q次图片
i
i
i,所以图片
i
i
i权值变为
w
i
+
q
wi+q
wi+q,因此喜欢的部分除去当前图片
i
i
i的概率为
x
+
k
−
1
−
(
w
[
i
]
+
q
)
s
u
m
−
(
j
−
k
)
+
k
−
1
\frac{x+k-1-(w[i]+q)}{sum-(j-k)+k-1}
sum−(j−k)+k−1x+k−1−(w[i]+q),(剩下的情都况按照这个模式转移就可以了)
2.遇到我喜欢的且当前是第
i
i
i张图片
3.遇到我不喜欢的(因为
a
[
i
]
a[i]
a[i]为
1
1
1,当前不可能是第
i
i
i张)
a
[
i
]
a[i]
a[i]为
0
0
0:
(这里需要注意因为
a
[
i
]
a[i]
a[i]为
0
0
0,所以
w
i
wi
wi的权值应当是减)
1.遇到我喜欢的(
a
[
i
]
a[i]
a[i]为
0
0
0,当前不可能是第
i
i
i个)
2.遇到我不喜欢的但不是第
i
i
i个
3.遇到我不喜欢的且是第
i
i
i个
主要思路就是上面这样了,具体细节和实现可以参考代码和注释:
ll dp[52][52][52][52];//对于第i个,当前一共访问了j次,k次是我喜欢的,q次是当前点的概率
int a[52];
int w[52];
ll inv[3100];
ll mi(ll a,ll b){
ll res=1;
while(b){
if(b%2){
res=res*a%mod;
}
a=a*a%mod;
b/=2;
}
return res;
}
void init(){
inv[0]=1;
for(int i=1;i<=3000;i++){
inv[i]=mi(i,mod-2);
}
}
ll ans[52];//对应期望
int main(){
/*cout<
/*cout<
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);//同步流
int n,m;
init();//求出inv逆元
cin>>n>>m;
ll sum=0;//总初始权值
ll x=0,y=0;//总喜欢的初始权值,总不喜欢的初始权值
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
cin>>w[i];
if(a[i]){
x+=w[i];
}
else{
y+=w[i];
}
sum+=w[i];
}
for(int i=1;i<=n;i++){
dp[i][0][0][0]=1;
for(int j=1;j<=m;j++){
for(int k=0;k<=j;k++){
for(int q=0;q<=j;q++){
if(a[i]){
//遇到我喜欢的但不是第i个
if(k>=1){
(dp[i][j][k][q]+=(dp[i][j-1][k-1][q]*(x+k-1-(w[i]+q))%mod)*inv[sum-(j-k)+k-1]%mod)%=mod;
}
//遇到我喜欢的且是第i个
if(k>=1&&q>=1){
(dp[i][j][k][q]+=(dp[i][j-1][k-1][q-1]*(w[i]+q-1)%mod)*inv[sum-(j-k)+k-1]%mod)%=mod;
}
//遇到我不喜欢的(a[i]为1,当前不可能是第i个)
(dp[i][j][k][q]+=(dp[i][j-1][k][q]*(y-(j-1-k))%mod)*inv[sum-(j-1-k)+k]%mod)%=mod;
}
else{
if(q>j-k){
continue;
}
//遇到我喜欢的(a[i]为0,当前不可能是第i个)
if(k>=1){
(dp[i][j][k][q]+=(dp[i][j-1][k-1][q]*(x+k-1)%mod)*inv[sum-(j-k)+k-1]%mod)%=mod;
}
//遇到我不喜欢的但不是第i个
(dp[i][j][k][q]+=(dp[i][j-1][k][q]*(y-(j-1-k)-(w[i]-q))%mod)*inv[sum-(j-1-k)+k]%mod)%=mod;
//遇到我不喜欢的且是第i个
if(q>=1){
(dp[i][j][k][q]+=(dp[i][j-1][k][q-1]*(w[i]-(q-1))%mod)*inv[sum-(j-1-k)+k]%mod)%=mod;
}
}
if(j==m){//计算每个w的最终期望
ll val=w[i];//w[i]的最终权值
if(a[i]){
val+=q;
}
else{
val-=q;
}
if(val>=0){//小于0的情况是不合法的
ans[i]=(ans[i]+dp[i][j][k][q]*val%mod)%mod;//对应期望,期望=权值*概率
}
}
}
}
}
cout<<ans[i]<<endl;
}
return 0;
}