题解 论文题 / [CF850F] Rainbow Balls
被强迫学习鞅与鞅的停时定理.jpg
读原论文时的笔记直接加在 pdf 上了,pdf 在云盘上
本题和倒数第二道例题十分相似
考虑对一个局面构造一个势函数 \(\phi\)
那么 \(\phi(A_t)+t\) 是一个鞅
可以利用 \(E(\phi(A_t)+t)=E(\phi(A_0)+0)\) 得到 \(E(t)=E(\phi(A_0))-E(\phi(A_t))\)
考虑构造这个势函数 \(\phi(A_i)=\sum f(a_i)\)
那么答案是
\[(\sum f(a_i))-(f(sum)+(n-1)f(0))
\]
那么写出转移式并化简得
\[\sum\frac{a_i(sum-a_i)}{sum(sum-1)}(f(a_{i}-1)+f(a_i+1)-2f(a_i))=-1
\]
一个套路是利用 \(\sum\frac{a_i}{sum}=1\) 来进一步化简要构造的东西
那么只要满足
\[f(a_i-1)+f(a_i+1)-2f(a_i)=\frac{1-sum}{sum-a_i}
\]
令 \(g(i)=f(i+1)-f(i)\),可以得到 \(g(i)\) 的递推式
列出 \(f(sum)\) 的式子来发现是可以化简的
剩下的暴力算出来就好了
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int a[N], lim;
const ll mod=1e9+7;
ll f[N], g[N], ans, sum;
inline ll qpow(ll a, ll b) {ll ans=1; for (; b; a=a*a%mod,b>>=1) if (b&1) ans=ans*a%mod; return ans;}
signed main()
{
freopen("ball.in", "r", stdin);
freopen("ball.out", "w", stdout);
n=read();
for (int i=1; i<=n; ++i) lim=max(lim, a[i]=read()), sum+=a[i];
for (int i=1; i<=lim; ++i) g[i]=(g[i-1]+(1-sum)*qpow(sum-i, mod-2))%mod;
for (int i=1; i<=lim; ++i) f[i+1]=(f[i]+g[i])%mod;
for (int i=1; i<=n; ++i) ans=(ans+f[a[i]])%mod;
ans=(ans-(1-sum)*(sum-1))%mod;
printf("%lld\n", (ans%mod+mod)%mod);
return 0;
}