版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
正题
这个问题很困难,没有好的概率期望基础是很难推导出来的。
首先考虑的就是这个问题的转化:
看到,你就知道p根本没有什么用,甚至不用把它输入进来。
可以把问题转化为一开始你有一个袋子,每次按顺序抽取任意两个球,把后者染成前者的颜色,再丢回去。
问期望多少次没有两种不同的颜色。
太多种颜色了,不好做,可以枚举一种颜色作为最后统一颜色白色,把其他颜色都看成黑色就可以了。
然后把每种颜色的期望步数都加起来就是答案。
注意这里的每种颜色的期望步数中产生贡献的只有最后统一颜色为白色的步数,若最后统一颜色为黑色,则将它视为0步。
因此答案并不会算重复。
我们先来看看概率:
用来表示当前有i个白球,个黑球,最后状态统一颜色为白色的概率。
先来讨论一个这样的东西:当期正处在i这个位置,往左走和往右走的概率都是一样的:都是。
当然,在这里不讨论0点和sum点。
很容易可以得到:
这个还是很容易理解的,因为第i个状态的下一个状态只能是。
所以,消一下项就可以得到上面那条式子了。
那么显然就是个等差数列了,
再来看看期望,用来表示i点最后统一颜色为白色的期望步数。
上面那条式子只有最后一项需要解释,因为说了如果最后状态为统一颜色为黑色,那么不计算在内,从i点出发的路径中只有种情况终点是sum,所以相当于给这些路径长度+1即可。
解出来发现,如果我们知道了第一项,那么就可以递推解出来n项了。
打表找规律可以发现
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
char s[N];
int tot[26];
double f[N];
int main(){
scanf("%s",s);
int len=strlen(s),mmax=0;
for(int i=0;i<len;i++) tot[s[i]-'A']++;
for(int i=0;i<26;i++) mmax=max(mmax,tot[i]);
f[1]=1.0*(len-1)*(len-1)/len;
for(int i=2;i<=mmax;i++)
f[i]=2*f[i-1]-f[i-2]-1.0*(len-1)/(len-i+1);
double ans=0;
for(int i=0;i<26;i++) ans+=f[tot[i]];
if(abs(ans)>=1e-1) printf("%.1lf",ans);
else printf("0.0");
}