P5516-[MtOI2019]小铃的烦恼【期望dp,线性消元】
正題
題目鏈接:https://www.luogu.com.cn/problem/P5516
題目大意
nnn個字母的一個字符串,每次隨機選取兩個不同的位置(x,y)(x,y)(x,y)讓第xxx個位置的字符變成第yyy個位置的字符。
求期望多少次能夠把所有字符變成同一個。
解題思路
因為最終狀態很多,所以我們考慮枚舉最終狀態,我們稱之為目標狀態。
設pip_ipi?表示目標狀態的字符有iii個時,該狀態變為最終狀態的概率,那么有pi=i(n?i)n(n?1)pi?1+n(n?1)?2i(n?i)n(n?1)+i(n?i)n(n?1)pi+1?pi=pi?1+pi+12p_i=\frac{i(n-i)}{n(n-1)}p_{i-1}+\frac{n(n-1)-2i(n-i)}{n(n-1)}+\frac{i(n-i)}{n(n-1)}p_{i+1}\Rightarrow p_i=\frac{p_{i-1}+p_{i+1}}{2}pi?=n(n?1)i(n?i)?pi?1?+n(n?1)n(n?1)?2i(n?i)?+n(n?1)i(n?i)?pi+1??pi?=2pi?1?+pi+1??
我們觀察一下這個式子,其實等價于pi?pi?1=pi+1?pip_i-p_{i-1}=p_{i+1}-p_{i}pi??pi?1?=pi+1??pi?表示ppp是一個等差數列,而p0=0,pn=1p_{0}=0,p_{n}=1p0?=0,pn?=1所以pi=inp_i=\frac{i}{n}pi?=ni?
然后設fif_ifi?表示目標狀態有iii個且是最終狀態的情況下到達最終狀態的期望步數,而因為 數學期望=概率×步數 ,和 單次期望=1單次概率\frac{1}{單次概率}單次概率1?
所以我們成功造成一次變化的期望次數是12i(n?i)n(n?1)\frac{1}{\frac{2i(n-i)}{n(n-1)}}n(n?1)2i(n?i)?1?,又因為多和少的概率是相等的,所以有方程
fipi=pin(n?1)2i(n?i)+pi+1fi+1+pi?1fi?12f_ip_i=p_i\frac{n(n-1)}{2i(n-i)}+\frac{p_{i+1}f_{i+1}+p_{i-1}f_{i-1}}{2}fi?pi?=pi?2i(n?i)n(n?1)?+2pi+1?fi+1?+pi?1?fi?1??
因為知道pi=inp_i=\frac{i}{n}pi?=ni?所以直接帶進去解出來就有
fi=n(n?1)2i(n?i)+i?12ifi?1+i+12ifi+1f_i=\frac{n(n-1)}{2i(n-i)}+\frac{i-1}{2i}f_{i-1}+\frac{i+1}{2i}f_{i+1}fi?=2i(n?i)n(n?1)?+2ii?1?fi?1?+2ii+1?fi+1?
換一個方式表達就是
(?i?12ifi?1)+(fi)+(?i+12ifi+1)=n(n?1)2i(n?i)(-\frac{i-1}{2i}f_{i-1})+(f_i)+(-\frac{i+1}{2i}f_{i+1})=\frac{n(n-1)}{2i(n-i)}(?2ii?1?fi?1?)+(fi?)+(?2ii+1?fi+1?)=2i(n?i)n(n?1)?
又有fn=0f_n=0fn?=0
這樣問題就變成了n?1n-1n?1個線性方程的方程組,因為每個方程組只有三個元,高斯消元會有大量多余步驟,所以我們直接手動先消掉fi?1f_{i-1}fi?1?再返回來消掉fi+1f_{i+1}fi+1?就好了。
時間復雜度O(n)O(n)O(n)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=2100; int n,num[26]; double f[N],a[N],ans; char s[N]; int main() {scanf("%s",s+1);n=strlen(s+1);for(int i=1;i<=n;i++)num[s[i]-'A']++;for(int i=1;i<=n;i++)f[i]=n*(n-1)/(2.0*i*(n-i));a[1]=1;for(int i=1;i<n;i++){double r=-(i+1)/(2.0*i),l=-i/(2.0*(i+1));double k=-l/a[i];f[i+1]+=f[i]*k;a[i+1]=1+k*r;}f[n]=0;for(int i=n-1;i>=1;i--){double r=-(i+1)/(2.0*i);f[i]-=f[i+1]*r,f[i]=f[i]/a[i];}for(int i=0;i<26;i++)ans+=num[i]*f[num[i]]/(double)n;printf("%.1lf\n",ans); }總結
以上是生活随笔為你收集整理的P5516-[MtOI2019]小铃的烦恼【期望dp,线性消元】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑配置怎么看xp系统(xp 看电脑配置
- 下一篇: Linux终端文件管理器(linux 终