题意:
给你一些照片,每个照片有权重,还分是否喜欢,每次拿起一张照片,拿这张照片的概率是 wi/sum 如果喜欢这张照片,那么它的重量就会+1,否则-1,问你拿m次之后每张照片的权重是多少。
题解:
一直想不出来啊,每次我都是想着怎么去将所有的照片一起做掉,但是忘了数据范围很小,其实可以每个都做一遍,也就是n*m*m*m的时间复杂度,那么对于每个数,有3种情况:拿它,拿除它意外喜欢的照片,拿除它以外不喜欢的照片,由于喜欢和不喜欢是捆成一个整体的,所以拿哪一张都无所谓,那么这三个的集合就是候选键,接下来就是记忆化搜索了,val[i][j][k]表示当概率为dp[i][j][k]的时候拿了i次它本身,j次除它喜欢的,k次除它不喜欢的期望,那么期望=值*概率,所以在pos=0的时候即可返回,在vis[i][j][k]的时候,注意val[i][j][k]只是概率为dp[i][j][k]时的期望,不一定是当前期望,所以要转换为值,也就是*dp[i][j][k],再乘上概率再返回。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=998244353;
ll qpow(ll a,ll b)
{
ll ans=1,ret=a;
while(b)
{
if(b&1)
ans=ans*ret%mod;
ret=ret*ret%mod;
b>>=1;
}
return ans;
}
ll dp[52][52][52],val[52][52][52],w[52];
int vis[52][52][52];
int f[52];
ll dfs(int pos,ll p,int i,int j,int k,ll na,ll nb,ll nc,int flag)
{
if(!pos)
return na*p%mod;
if(vis[i][j][k])
return qpow(dp[i][j][k],mod-2)*val[i][j][k]%mod*p%mod;
dp[i][j][k]=p;
val[i][j][k]+=dfs(pos-1,p*na%mod*qpow(na+nb+nc,mod-2)%mod,i+1,j,k,max(0ll,na+flag),nb,nc,flag);
val[i][j][k]+=dfs(pos-1,p*nb%mod*qpow(na+nb+nc,mod-2)%mod,i,j+1,k,na,nb+1,nc,flag);
val[i][j][k]+=dfs(pos-1,p*nc%mod*qpow(na+nb+nc,mod-2)%mod,i,j,k+1,na,nb,max(0ll,nc-1),flag);
val[i][j][k]%=mod;
vis[i][j][k]=1;
return val[i][j][k];
}
int main()
{
int n,m;
ll like=0,dis=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&f[i]);
for(int i=1;i<=n;i++)
{
scanf("%lld",&w[i]);
if(f[i])
like+=w[i];
else
dis+=w[i];
}
ll ans;
for(int i=1;i<=n;i++)
{
memset(dp,0,sizeof(dp));
memset(val,0,sizeof(val));
memset(vis,0,sizeof(vis));
if(f[i])
ans=dfs(m,1,0,0,0,w[i],like-w[i],dis,1);
else
ans=dfs(m,1,0,0,0,w[i],like,dis-w[i],-1);
printf("%lld\n",ans);
}
printf("\n");
return 0;
}