文章目录
- 题目描述
- 解析
- 代码
题目描述
解析
首先,可以使用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;
}
/**/