题目描述
解析
首先,可以使用dp解决本题
设fi,j,k:操作i轮之后编号j的小球有k个的概率
转移和统计答案就都不难了
但是还有一个问题
不难发现这个题循环下去是可以无穷无尽的
所以限定一个i的上界(如500000),在损失精度可以接受的前提下使答案可求
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e7+100;
const int mod=20040313;
int n,num[28],id[28],tot;
char s[28];
double dp[2][28][28];
int main(){
scanf("%s",s+1);
tot=strlen(s+1);
for(int i=1;i<=tot;i++){
int now=s[i]-'A'+1;
if(id[now]==0) id[now]=++n;
num[id[now]]++;
//printf("s=%c id=%d num=%d\n",s[i],id[now],num[id[now]]);
}
for(int i=1;i<=n;i++){
//printf("i=%d num=%d\n",i,num[i]);
dp[1][i][num[i]]=1.0;
}
int now=1;
double ans=0;
for(int k=0;k<=50000;k++){
for(int i=1;i<=n;i++) ans+=dp[now][i][tot]*k;
now^=1;int pre=now^1;
for(int i=1;i<=n;i++){
for(int j=0;j<=tot;j++) dp[now][i][j]=0;
}
//printf("k=%d now=%d pre=%d\n",k,now,pre);
for(int i=1;i<=n;i++){
for(int j=0;j<tot;j++){
double p=1.0*j*(tot-j)/(tot*(tot-1));
//printf(" col=%d num=%d dp=%lf p=%lf\n",i,j,dp[pre][i][j],p);
if(j>0) dp[now][i][j-1]+=dp[pre][i][j]*p;
dp[now][i][j+1]+=dp[pre][i][j]*p;
dp[now][i][j]+=dp[pre][i][j]*(1.0-2*p);
}
}
//printf("k=%d ans=%lf\n",k,ans);
}
printf("%.6lf\n",ans);
return 0;
}
/*
*/