[題解] Codeforces 1349 D Slime and Biscuits 概率,推式子,DP,解方程
題目
神題。很多東西都不知道是怎麼湊出來的,隨意設定幾個變數,之間就產生了密切的關係。下次碰到這種題應該還是不會做罷。
令\(E_x\)為最後結束時所有的餅乾都在第x個人手中的概率*時間的和。\(ans=\sum E_x\)。
令\(C\)為現在所有的餅乾都在第x個人手中,要將它們全部轉移到第y(\(x \neq y\))個人手中的期望步數。顯然對於所有的x,y,C都是相同的。
令\(P_i\)為遊戲結束時,所有餅乾都在第i人手中的概率。
假設篡改遊戲規則,餅乾全在第x個人手中時遊戲才結束。令此時的期望步數為\(E'_x\)。
那麼就有如下等式:
\[E'_x=E_x+\sum_{i \neq x} E_i+P_iC \]證明就考慮\(E'_x\)
所以求出所有\(E'_x\)和\(C\)就行了。令\(f_i\)表示需要把所有餅乾都移動到某個人手中,這個人手中現在有i個餅乾的還需要的步數。(反正想想轉移就發現是可以這樣DP的) 轉移為(\(m表示\sum a_i\)):
\(f_m=0\)
\(f_0=1+\frac{n-2}{n-1}f_0+\frac{1}{n-1}f_1\)(每塊餅乾有n-1種走法,n-2/n-1種走到別的人手裡,1/n-1種走到這個人手裡)
其他:\(f_i=1+\frac{i}{m}f_{i-1}+\frac{m-i}{m}(\frac{n-2}{n-1}f_i+\frac{1}{n-1}f_{i+1})\)(先討論動手裡的還是外面的餅乾)
把最後一個式子化成\(Af_{i-1}+(B-1)f_i+Cf_{i+1}+1=0\)的形式,通過推出這個式子的過程可以發現\(A+B+C=0\)(因為是三種可能性的概率和)。三個未知數不好處理,我們把f差分一下,令\(g_i=f_i-f_{i+1}\)
先試試如果\(g_{i-1}\)的係數是A會怎麼樣。顯然應該讓\(f_i\)的係數=B。發現剛好得到了一個合法的式子\(Ag_{i-1}+(A+B-1)g_i+1=0\)(記得A+B+C=0)。
由第一個轉移式知道\(g_0=n-1\)所以就可以遞推出所有\(g_i\),求個字尾和就是\(f_i\),這題就做完了。時間複雜度\(O(n)\),下面程式碼裡寫的\(O(nlogn)\),因為懶。
點選檢視程式碼
#include <bits/stdc++.h>
#define rep(i,n) for(LL i=0;i<n;++i)
#define repn(i,n) for(LL i=1;i<=n;++i)
#define LL long long
#define pii pair <LL,LL>
#define fi first
#define se second
#define mpr make_pair
#define pb push_back
using namespace std;
const LL MOD=998244353;
LL qpow(LL x,LL a)
{
LL res=x,ret=1;
while(a>0)
{
if((a&1)==1) ret=ret*res%MOD;
a>>=1;
res=res*res%MOD;
}
return ret;
}
LL n,a[100010],g[300010],m=0,f[300010];
int main()
{
cin>>n;
rep(i,n) scanf("%lld",&a[i]),m+=a[i];
g[0]=n-1;
repn(i,m-1)
{
LL A=i*qpow(m,MOD-2)%MOD,B=(m-i)*(n-2)%MOD*qpow(m,MOD-2)%MOD*qpow(n-1,MOD-2)%MOD;
g[i]=(MOD+MOD-1-A*g[i-1]%MOD)*qpow((A+B-1+MOD)%MOD,MOD-2)%MOD;
}
f[m]=0;
for(int i=m-1;i>=0;--i) f[i]=(f[i+1]+g[i])%MOD;
LL ans=0;
rep(i,n) (ans+=f[a[i]])%=MOD;
(ans+=MOD-(n-1)*f[0]%MOD)%=MOD;
(ans*=qpow(n,MOD-2))%=MOD;
cout<<ans<<endl;
return 0;
}