题意:nnn个人共有mmm个饼干,每轮随机选一个饼干随机给一个另外的人,所有饼干都在一个人手里时游戏结束,求期望进行次数。模998244353998244353998244353。
n≤105,m≤3×105n\leq10^5,m\leq3\times10^5n≤105,m≤3×105
首先肯定是每个人作为最终获得所有饼干的人分别考虑。
但是如果只考虑这个人的话,无法确定游戏进行过程中是否已经在其他人那里结束了。
所以干脆改下规则:设当前考虑的人为xxx,规定只有xxx收集完所有饼干后游戏才结束。也就是有人收集完了所有饼干后,如果他不是xxx,游戏继续进行;否则游戏立即结束。
为了后面讲清楚,这里给一个不正式的严谨定义:设R,R1∼RnR,R_1\sim R_nR,R1∼Rn表示游戏遵循的规则,其中RRR表示任何一个人收集了所有饼干后游戏结束,即原来的规则。Rx(x∈[1,n])R_x(x\in[1,n])Rx(x∈[1,n])表示只有xxx收集完游戏才结束的新规则。
设在RxR_xRx下游戏期望进行的次数为Ex′E_x'Ex′。即:设f′(x,i)f'(x,i)f′(x,i)表示游戏进行了iii步后结束且xxx获得了所有饼干的概率,Ex′=∑i=0∞i⋅f′(x,i)E'_x=\sum_{i=0}^{\infin}i\cdot f'(x,i)Ex′=∑i=0∞i⋅f′(x,i)
注:这个f′(x,i)f'(x,i)f′(x,i)和后面的f(x,i)f(x,i)f(x,i)只是为了方便理解定义,对推导没有影响。
我们考虑寻找新的规则和原来的规则的联系
在RRR下,设PxP_xPx表示游戏结束时所有饼干在xxx手上的概率,ExE_xEx表示所有饼干在xxx手上结束的所有情况 的 概率乘以时间 之和。(注意不是期望,概率的分母包括了在其他人那里结束的情况)
即:设f(x,i)f(x,i)f(x,i)表示游戏进行iii步后结束,xxx获得所有饼干的概率,Ex=∑i=0∞i⋅f(x,i),Px=∑i=0∞f(x,i)E_x=\sum_{i=0}^{\infin}i\cdot f(x,i),P_x=\sum_{i=0}^\infin f(x,i)Ex=∑i=0∞i⋅f(x,i),Px=∑i=0∞f(x,i)
有∑i=1nPi=1,∑i=1nEi=ans\sum_{i=1}^n P_i=1,\sum_{i=1}^nE_i=ans∑i=1nPi=1,∑i=1nEi=ans,ansansans为题目所求
设CCC表示在RjR_jRj下,现在所有饼干在iii手上且i≠ji\neq ji=j,游戏期望还要进行多少步。显然这是个与i,ji,ji,j无关的常数。
考虑用ExE_xEx表示出Ex′E_x'Ex′
为了方便,我们称一个状态为iii类关键点,当且仅当这个状态的所有饼干都在iii手上。
考虑在RxR_xRx下的一场游戏,如果它只有结束状态这一个关键点,期望步数为ExE_xEx
否则我们枚举第一个关键点的类别iii,显然i≠xi\neq xi=x,不然游戏会提前结束。然后从这个关键点开始就是 从“所有点都在iii手上”这个状态开始的RxR_xRx游戏,期望步数为CCC
所以:
Ex′=Ex+∑i=1n[i≠x](Ei+PiC)E'_x=E_x+\sum_{i=1}^n[i\neq x](E_i+P_iC)Ex′=Ex+i=1∑n[i=x](Ei+PiC)
如果你想不通为什么CCC要乘上PiP_iPi:
前面说过,Ex=∑i=0∞if(x,i)E_x=\sum_{i=0}^\infin if(x,i)Ex=∑i=0∞if(x,i)
换句话说,对于每一个iii,都有f(x,i)f(x,i)f(x,i)的可能性在iii步后 所有饼干都在xxx手上,在这里就是到达枚举的第一个关键点。
在这之后还需要CCC步来到最终结束的状态,即∑i=0∞(i+C)f(x,i)\sum_{i=0}^\infin(i+C)f(x,i)∑i=0∞(i+C)f(x,i)
而Px=∑i=0∞f(x,i)P_x=\sum_{i=0}^{\infin}f(x,i)Px=∑i=0∞f(x,i),所以加上PiCP_iCPiC就可以了
拆一下:
Ex′=Ex+∑i=1n[i≠x](Ei+PiC)E'_x=E_x+\sum_{i=1}^n[i\neq x](E_i+P_iC)Ex′=Ex+i=1∑n[i=x](Ei+PiC)
Ex′=Ex+∑i=1n[i≠x]Ei+∑i=1n[i≠x]PiCE'_x=E_x+\sum_{i=1}^n[i\neq x]E_i+\sum_{i=1}^n[i\neq x]P_iCEx′=Ex+i=1∑n[i=x]Ei+i=1∑n[i=x]PiC
Ex′=∑i=1nEx+C∑i=1n[i≠x]PiE'_x=\sum_{i=1}^nE_x+C\sum_{i=1}^n[i\neq x]P_iEx′=i=1∑nEx+Ci=1∑n[i=x]Pi
Ex′=ans+C(1−px)E'_x=ans+C(1-p_x)Ex′=ans+C(1−px)
对x=1∼nx=1\sim nx=1∼n求和
∑i=1nEi′=n⋅ans+C(n−1)\sum_{i=1}^nE'_i=n\cdot ans+C(n-1)i=1∑nEi′=n⋅ans+C(n−1)
只要求出Ex′E'_xEx′和CCC的值,问题就解决了!
而CCC是严格包含于Ex′E_x'Ex′的,所以我们的目标是解决新规则下的问题。
注意到在RxR_xRx下,我们并不关心每个饼干具体在谁手上,我们只关心它在不在xxx手上
所以可以设f(i)f(i)f(i)表示当前xxx手上有iii个饼干时期望进行次数。
f(i)={1+1n−1f(i+1)+n−2n−1f(i)x=01+imf(i−1)+m−im(1n−1f(i+1)+n−2n−1f(i))0<x<m0x=mf(i)= \begin{cases} 1+\frac{1}{n-1}f(i+1)+\frac{n-2}{n-1}f(i)& x=0\\ 1+\frac{i}mf(i-1)+\frac{m-i}{m}(\frac{1}{n-1}f(i+1)+\frac{n-2}{n-1}f(i))& 0<x<m\\ 0 & x=m \end{cases}f(i)=⎩⎪⎨⎪⎧1+n−11f(i+1)+n−1n−2f(i)1+mif(i−1)+mm−i(n−11f(i+1)+n−1n−2f(i))0x=00<x<mx=m
解出这个方程就好了
暴力硬推是一种方法,这里有一个很优美的思路:
考虑中间的式子,记为
f(i)=Af(i−1)+Bf(i)+Cf(i+1)+1f(i)=Af(i-1)+Bf(i)+Cf(i+1)+1f(i)=Af(i−1)+Bf(i)+Cf(i+1)+1
Af(i−1)+(B−1)f(i)+Cf(i+1)+1=0Af(i-1)+(B-1)f(i)+Cf(i+1)+1=0Af(i−1)+(B−1)f(i)+Cf(i+1)+1=0
注意到A+B+C=1A+B+C=1A+B+C=1,设g(i)=f(i)−f(i+1)g(i)=f(i)-f(i+1)g(i)=f(i)−f(i+1)
A⋅g(i−1)+(A+B−1)g(i)+1=0A\cdot g(i-1)+(A+B-1)g(i)+1=0A⋅g(i−1)+(A+B−1)g(i)+1=0
g(i)=A⋅g(i−1)+1Cg(i)=\frac{A\cdot g(i-1)+1}{C}g(i)=CA⋅g(i−1)+1
这样推一次就可以把ggg算出来,求个后缀和就得到了fff
然后Ex′=f(ai),C=f(0)E_x'=f(a_i),C=f(0)Ex′=f(ai),C=f(0)
复杂度O(n)O(n)O(n)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#define MAXN 300005
using namespace std;
inline int read()
{int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans;
}
const int MOD=998244353;
typedef long long ll;
inline int qpow(int a,int p)
{int ans=1;while (p){if (p&1) ans=(ll)ans*a%MOD;a=(ll)a*a%MOD;p>>=1;}return ans;
}
#define inv(x) qpow(x,MOD-2)
inline int add(const int& x,const int& y){return x+y>=MOD? x+y-MOD:x+y;}
inline int dec(const int& x,const int& y){return x<y? x-y+MOD: x-y;}
int a[MAXN],f[MAXN];
int main()
{int n=read(),m=0;for (int i=1;i<=n;i++) m+=(a[i]=read());f[0]=n-1;for (int i=1;i<m;i++) f[i]=((ll)i*inv(m)%MOD*f[i-1]%MOD+1)*m%MOD*(n-1)%MOD*inv(m-i)%MOD;for (int i=m;i>=0;i--) f[i]=add(f[i],f[i+1]);int sum=0;for (int i=1;i<=n;i++) sum=add(sum,f[a[i]]);sum=dec(sum,f[0]*(n-1ll)%MOD);sum=(ll)sum*inv(n)%MOD;cout<<sum;return 0;
}