[CF850F]Rainbow Balls


\(\text{Tip}\):感謝此篇題解對我的巨大幫助,故記錄一下式子的推導過程。

\(\text{Problem}\)題目鏈接

\(\text{Solution}\)

有多種顏色的球,且要求最后剩下的球顏色相同。故考慮枚舉最后留下的球的顏色 \(x\)

\(F_{i}\) 表示當前有 \(i\) 個顏色為 \(x\) 的球,把所有球都變成顏色為 \(x\) 的期望時間,再記 \(S\) 表示球的總和,即 \(S=\sum\limits_{i=1}^{n}a_{i}\)。顯然 \(F_{0}\) 這個狀態不存在,且 \(F_{S}=0\)。記 \(P_{i}\) 表示當前有 \(i\) 個顏色為 \(x\) 的球時,選出兩個球顏色不同且其中至少有一個球顏色為 \(x\) 的概率,則 \(P_{i}=\cfrac{i(s-i)}{s(s-1)}\)。記 \(v_{i}\) 表示每次轉移時貢獻的期望時間,則對於 \(\forall i\in[1,S-1]\)易得:

\[\qquad F_{i}=P_{i}(F_{i-1}+F_{i+1})+(1-2P_{i})F_{i}+v_{i} \qquad \]

此處有個很關鍵的地方,就是 \(v_{i}\not=1\)。考慮其原因,發現當 \(i\leq0\) 時答案不存在,所以需要考慮能從 \(i\) 到達 \(S\) 的貢獻,而走一步的期望就相當於 \(i\) 能走到 \(S\) 的概率。而這是個經典問題,簡述為:數軸上有一個點 \(p\) 每次等概率向左或向右走,也可以不走,問能走到 \(S\) 的概率。該問題解法如下:

\(G_{i}\) 表示從 \(i\) 能走到 \(S\) 的概率,那么有:

\[\qquad G_{i}=P_{i}(G_{i-1}+G_{i+1})+(1-2P_{i})G_{i} \qquad \]

其中邊界條件顯然為 \(G_{0}=0,G_{S}=1\)。上式可解得 \(2G_{i}=G_{i-1}+G_{i+1}\)。發現 \(G_{i+1}-G_{i}=G_{i}-G_{i-1}\),則對於數列 \(\{G_{i}-G_{i-1}\}(1\leq i\leq S)\),構成一個等差數列 。

故得到 \(G_{i}=\cfrac{i}{S}\)

於是 \(v_{i}=G_{i}=\cfrac{i}{S}\),則轉移方程為:

\[\qquad F_{i}=P_{i}(F_{i-1}+F_{i+1})+(1-2P_{i})F_{i}+\cfrac{i}{S} \qquad \]

着手拆開這個式子,得到:

\[\qquad 2P_{i}F_{i}=P_{i}(F_{i-1}+F_{i+1})+\cfrac{i}{S} \qquad \]

\(P_{i}=\frac{i(S-i)}{S(S-1)}\) 代入,得到:

\[\qquad 2F_{i}=F_{i-1}+F_{i+1}+\cfrac{S-1}{S-i} \qquad \]

\[\qquad F_{i}-F_{i+1}=F_{i-1}-F_{i}+\cfrac{S-1}{S-i} \qquad \]

發現通過這個式子,可以對於所有的 \(i\in[2,S]\),把 \(F_{i-1}-F_{i}\) 轉換為 \(F_{1}-F_{2}\),考慮求出它。

發現 \(F_{0}\) 不存在。於是對於 \(i=1\),可以算出:

\[\qquad F_{1}=F_{2}P_{1}+(1-2P_{1})F_{1}+\cfrac{1}{S} \qquad \]

\[\qquad 2P1F_{1}=P_{1}F_{2}+\cfrac{1}{S} \qquad \]

發現 \(P_{1}=\frac{1}{S}\),則得到:\(F_{2}=2F_{1}-1\)

故考慮如何使用上面的關鍵性質。發現 \(F_{S}=0\),則 \(F_{1}=F_{1}-F_{S}\),故有:

\[\qquad F_{1}-F_{S}=\sum\limits_{i=2}^{S}F_{i-1}-F_{i} \qquad \]

考慮如何快速的把 \(F_{i-1}-F_{i}\) 快速轉化為與 \(F_{1}-F_{2}\) 有關的式子:

\[\qquad F_{i-1}-F_{i}=F_{1}-F_{2}+\sum\limits_{j=2}^{i-1}\cfrac{S-1}{S-j} \qquad \]

發現對於 \(\sum\limits_{i=2}^{S}F_{i-1}-F_{i}\) 來說,不必 \(O(S^2)\) 爆求式子的原因是后面枚舉貢獻的式子重復。發現對於 \(j\) 來說,計算 \(\cfrac{S-1}{S-j}\) 的次數為 \((S-j)\) 次。則得到:

\[\qquad \sum\limits_{i=2}^{S}F_{i-1}-F_{i}=(S-1)(F_{1}-F_{2})+\sum\limits_{j=2}^{S-1}(S-1) \qquad \]

於是把 \(F_{2}=2F_{1}-1\) 代入上式,即可用 \(S\) 表達出 \(F_{1}\)

\[\qquad F_{1}=\cfrac{(S-1)^2}{S} \qquad \]

然后我們可以通過 \(F_{1}\) 求出 \(F_{2}\),那么可以直接通過 \(O(S\log P)\) 的時間復雜度求出 \(F\) 的每一項(\(P\) 為本題中的模數)。

發現 \(S=\sum\limits_{i=1}^{n}a_{i}\approx 2.5\times 10^{8}\),數組開不下。考慮最終答案是 \(\sum\limits_{i=1}^{n}F_{a_{i}}\),故記 \(W=max\{a_{i}\}\),我們只需要求到 \(F_{W}\) 即可,時間復雜度為 \(O(W\log P)\),空間復雜度為 \(O(W)\),發現 \(W\leq10^{5}\),可以通過本題。

\(\text{Code}\)

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <bitset>
#define ri register
#define inf 0x7fffffff
#define E (1)
#define mk make_pair
#define int long long
//#define double long double
using namespace std; const int N=200010, Mod=1e9+7;
inline int read()
{
    int s=0, w=1; ri char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch-'0'), ch=getchar();
    return s*w;
}
void print(int x) { if(x<0) x=-x, putchar('-'); if(x>9) print(x/10); putchar(x%10+'0'); }
int n,a[N],dp[N],S;
inline int ksc(int x,int p) { int res=1; for(;p;p>>=1, x=x*x%Mod) if(p&1ll) res=res*x%Mod; return res; }
signed main()
{
    n=read();
    for(ri int i=1;i<=n;i++) a[i]=read(), S+=a[i];
    dp[1]=ksc(S,Mod-2)%Mod*(S-1)%Mod*(S-1)%Mod;
    dp[2]=dp[1]*2-1, dp[2]%=Mod;
    for(ri int i=3;i<=min((int)1e5,S-1);i++) dp[i]=(dp[i-1]*2-dp[i-2]-(S-1)%Mod*ksc(S-i+1,Mod-2)%Mod)%Mod, dp[i]=(dp[i]+Mod)%Mod;
    int res=0;
    for(ri int i=1;i<=n;i++) res=(res+dp[a[i]])%Mod;
    printf("%lld\n",res);
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM