【CF1349D】Slime and Biscuits(势能函数)

点此看题面

  • 有\(n\)个人,第\(i\)个人有\(a_i\)块饼干。
  • 每个回合等概率选择一块饼干等概率送给除当前所有者外的一个人。
  • 求期望多少回合后所有饼干在一个人手上。
  • \(n\le10^5,\sum a_i\le3\times10^5\)

势能函数

关于势能函数可见【CF1025G】Company Acquisitions

设饼干总数为\(A\)。在这道题中,对于一个局面只需要知道每个人的饼干块数\(a_{1\sim n}\),因此不妨设一个局面的势能函数\(F(a_{1\sim n})=\sum_{i=1}^nf(a_i)\)。

考虑每个人在一轮后饼干数量不变或\(\pm1\)三种情况各自的概率,列出方程:

\[\sum_{i=1}^n(\frac{a_i}{A}f(a_i-1)+\frac{A-a_i}{A}\cdot\frac1{n-1}\cdot f(a_i+1)+\frac{A-a_i}A\cdot\frac{n-2}{n-1}\cdot f(a_i))-\sum_{i=1}^nf(a_i)=1 \]

单独考虑某一个拥有\(x\)块饼干的人:

\[\frac{x}{A}f(x-1)+\frac{A-x}{A}\cdot\frac1{n-1}\cdot f(x+1)+\frac{A-x}A\cdot\frac{n-2}{n-1}\cdot f(x)-f(x)=\frac{x}A \]

变个形:

\[f(x+1)=(\frac {A(n-1)}{A-x}-(n-2))f(x)-\frac{x(n-1)}{A-x}f(x-1)+\frac{x(n-1)}{A-x}\\ \]

不妨设\(f(0)=0\),代入可得\(f(1)=0\),剩下的就可以利用这个式子直接递推了。

最终答案为\(f(A)-\sum_{i=1}^nf(a_i)\)。

代码:\(O(AlogA)\)

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Rg register
#define RI Rg int
#define Cn const
#define CI Cn int&
#define I inline
#define W while
#define N 100000
#define V 300000
#define X 998244353
using namespace std;
int n,a[N+5],f[V+5];I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;} 
int main()
{
	RI i,A=0;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d",a+i),A+=a[i];
	RI t;for(i=1;i^A;++i) t=1LL*(n-1)*QP(A-i,X-2)%X,f[i+1]=((1LL*A*t-(n-2)+X)%X*f[i]-1LL*i*t%X*f[i-1]%X+X+1LL*i*t)%X;//递推
	for(t=f[A],i=1;i<=n;++i) t=(t-f[a[i]]+X)%X;return printf("%d\n",t),0;//最终局面-初始局面
}
上一篇:Linux下awk理解


下一篇:15awk命令