题解-bzoj2554 Color

Problem

Please contact lydsy2012@163.com!

题意概要:有 \(n\) 个球排成一列,每个球都有一个颜色,每次随机选出两个球,使得后者染上前者的颜色,求期望操作多少次,才能使得所有球的颜色都一样?

\(n\leq 10^4\)

Solution

思想和这篇差不多,但推导方面可能更详尽

推这题用了大半张草稿纸的说 最近用纸效率剧增啊

考虑只要找出对于每一种颜色\(C\),整个序列最终全部变为\(C\)的情况

设整个序列最终变为颜色 \(i\) 的概率为\(p_i\),期望步数为 \(g_i\),则答案可以表示为

\(Ans=\sum p_ig_i\)

(这里的变量与下文冲突时以下文为准,这里的变量只是作表达作用)

但是要注意,这里的期望步数是在“序列最终变为颜色\(i\)”前提下的期望,是一种条件期望

然后如果想让序列变为颜色 \(i\) ,则对于当前序列而言,只有“是颜色\(i\)”和“不是颜色\(i\)”这两种情况,所以可以将情况化简为一个\(01\)序列,且当前有\(i\)\(1\),求所有元素变为\(1\)的概率和期望步数


先来解决概率问题

所有操作共有\(n(n-1)\)个,若当前有\(i\)\(1\),则会改变\(1\)的数量的只有 \(2i(n-i)\)种操作,而且其中会使序列增加一个\(1\)的有其中的一半\(i(n-i)\)种,而使序列减少一个\(1\)的也有\(i(n-i)\)种。即每个回合有\(\frac {i(n-i)}{n(n-1)}\)的概率使\(i\)加一,有\(\frac {i(n-i)}{n(n-1)}\)的概率使\(i\)减一,还有\(1-\frac {2i(n-i)}{n(n-1)}\)的概率没有变化

\(p_i\)表示当目前有\(i\)\(1\)时,最终变为颜色\(i\)的概率

由于若已经没有\(1\),则再没有可能使整个序列变为\(1\)了,所以有\(p_0=0\),类似的,有\(p_n=1\)

由分析中\(i\)上升下降概率相同,可以列出\(p_i=\frac {p_{i-1}+p_{i+1}}2,i\in(0,n)\)

由于表達的是等差数列,所以可以轻松得到\(p_i=\frac in\)


再來解決期望问题

考虑到每次操作有一定几率不会对局面进行影响,影响成功的几率为\(\frac {2i(n-i)}{n(n-1)}\),根据期望问题的性质,则期望操作\(\frac {n(n-1)}{2i(n-i)}\)次会对局面影响一次

\(f_i\)表示当前有\(i\)\(1\)时序列变为颜色\(i\)的期望步数

则得到方程:\(f_i=\frac {n(n-1)}{2i(n-i)}+\frac 12f_{i-1}+\frac 12f_{i+1}\)

但是这样就错了

因为当前要算的是条件期望,而当局面内有\(i-1\)\(1\)和有\(i+1\)\(1\)时整个序列全变\(1\)的概率不一样,由于期望计算是概率乘以权值,所以两者的比例不能简单计算为\(1:1\)

相应的,由之前计算的概率可以得到,若当前局面有\(i-1\)\(1\),则整个序列全变\(1\)的概率为\(\frac {i-1}n\),相应的,有\(i+1\)\(1\)时概率为\(\frac {i+1}n\),又由于当前状态只有这两种后继状况,所以两个概率应除以两个概率的和

所以上面的方程需要变化为:

\(f_i=\frac {n(n-1)}{2i(n-i)}+\frac {i-1}{2i}f_{i-1}+\frac {i+1}{2i}f_{i+1}\)

然后利用之前学习的线性高斯消元就可以套路解决了

(这里还是写一下吧,别到时候看这题的时候又推一整版草稿纸)

\(f_i=k_if_{i+1}+b_i\)

考虑利用这个式子将上面方程进行消元,将这个式子中带入方程右边的第二项,得到

\[f_i=\frac {n(n-1)}{2i(n-i)}+\frac {i-1}{2i}k_{i-1}f_i+\frac {i-1}{2i}b_{i-1}+\frac {i+1}{2i}f_{i+1} \]

\[(1-\frac {i-1}{2i}k_{i-1})f_i=\frac {i+1}{2i}f_{i+1}+\frac {i-1}{2i}b_{i-1}+\frac {n(n-1)}{2i(n-i)} \]

\[f_i=\frac {\frac {i+1}{2i}}{1-\frac {i-1}{2i}k_{i-1}}f_{i+1}+\frac {\frac {i-1}{2i}}{1-\frac {i-1}{2i}k_{i-1}}b_{i-1}+\frac {\frac {n(n-1)}{2i(n-i)}}{1-\frac {i-1}{2i}k_{i-1}} \]

和之前设置的状态\(f_i=k_if_{i+1}+b_i\)相比,可以得到

\[\begin{equation} \begin{cases} k_i = \frac {\frac {i+1}{2i}}{1-\frac {i-1}{2i}k_{i-1}} \\ b_i = \frac {\frac {i-1}{2i}b_{i-1}+\frac {n(n-1)}{2i(n-i)}}{1-\frac {i-1}{2i}k_{i-1}} \end{cases} \end{equation} \]

然后由于\(f_0\)没有意义,就无需从此转移,所以得到特殊情况

\(f_1=\frac {n(n-1)}{2\times 1\cdot (n-1)}+f_2=\frac n2+f_2\)

又由于\(f_1=k_1f_2+b_1\),可以得到在\(i=1\)下的特殊情况:\(\begin {cases}k_1=1\\b_1=\frac n2\end{cases}\)

由第一项和上面得到的递推公式,可以推得所有的\(k_i,b_i\),又由于\(f_n=0\),可以轻易得到所有的\(f_i\)


最终统计答案

若一种颜色出现了\(c\)次,则这个颜色对答案的贡献为\(\frac cn\cdot f_c\)

Code

代码还是很短的

#include <cstdio>

const int N=10103;
double k[N],b[N],f[N];
char s[N];int n,ct[26];

int main(){
	scanf("%s",s+1);
	for(n=1;s[n];++n)
		++ct[s[n]-'A'];
	--n;k[1]=1,b[1]=0.5*n;
	double iv,bs;
	for(int i=2;i<n;++i){
		iv=0.5/i;
		bs=1.0/(1-(i-1)*iv*k[i-1]);
		k[i]=(i+1) * iv * bs;
		b[i]=((i-1) * iv * b[i-1]  +  n*(n-1)* iv / (n-i) ) * bs;
	}
	
	for(int i=n-1;i;--i)
		f[i]=k[i]*f[i+1]+b[i];
	
	double ans=0.0;
	for(int i=0;i<26;++i)
		ans+=1.0*ct[i]/n*f[ct[i]];
	printf("%.1lf\n",ans);
	return 0;
}
posted @ 2019-01-11 20:14  oier_hzy  阅读(255)  评论(0编辑  收藏  举报