Loading

停时定理

时停停时定理的优质boke

简要概括一下使用前提,就是每一步对期望 产生的贡献都相等,比如每秒移动一次,每次操作一下等等,基本上没有啥题不满足的,其次是到达终态后立即停止,不能求第二次经过等等

通俗理解一下就是我们要让结束状态在“最底下”(无法再转移),才能用势能差的方式计算期望

一般设 $ \Phi = \sum f $ ,在转移只跟 $ f $ 的参数有关时,根据转移式子推导出 $ f $ 的计算方式,最后求出终末 $ \Delta \Phi $ 即是答案

本文完结

其中比较不是非常友好但是不算太不友好的两道题的公式推导(最不友好的的那道题不会)

CF1349D Slime and Biscuits

\[ \begin{aligned} \sum_{i=1}^n f(a_i)-1 &= \sum_{i=1}^n \frac{a_i}{m} \left( f(a_i-1) + \frac{1}{n-1} \sum_{j \neq i} \left( (n-2)f(a_j) + f(a_j+1) \right) \right) \\ &= \sum_{i=1}^n \frac{a_i}{m} f(a_i-1) + \frac{(m-a_i)(n-2)}{m(n-1)} \sum_{i=1}^n f(a_i) + \frac{m-a_i}{m(n-1)} \sum_{i=1}^n f(a_i+1) \\ \end{aligned} \]

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

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

代入 $ x = 0 $ 发现 $ f(0) = f(1) =0 $

code

#include <iostream>
#include <vector>
#define Sakura int
#define Re register ll
#define _ putchar(' ')
#define el putchar('\n')
#define ll long long
#define fre(x,y) freopen(#x".in","r",stdin),freopen(#y".out","w",stdout);

using namespace std;

const ll maxn=500+10;
const ll mod=1e9+7;

inline ll read(){
    ll x=0,f=0;char c=getchar();
    while(!isdigit(c)) f|=c=='-',c=getchar();
    while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return f?-x:x;
}

inline void ot(ll x) {
    if(x<0) putchar('-'),x=-x;
    if(x>9) ot(x/10);putchar(x%10|48);
}

inline ll qpow(ll x,ll d) {
	ll res=1;
	while(d) {
		if(d&1) res=res*x%mod;
		x=x*x%mod;
		d>>=1;
	}
	return res;
}

ll n;
ll a[maxn];
ll ans;

Sakura main() {
	n=read();
	for(Re i=1;i<=n;++i) {
		ll x=read();
		if(x>0) a[x]++;
	}
	for(Re i=1;i<=n;++i) if(a[i]) (ans-=qpow(2,a[i])-1)%=mod;
	(ans+=qpow(2,n-1)-1)%=mod;
	if(ans<0) ans+=mod;
	ot(ans);
}

CF850F Rainbow Balls

\[ \begin{aligned} \sum_{i=1}^n f(a_i) -1 &= \sum_{i=1}^n \frac{a_i}{m} \left( \frac{a_i-1}{m-1} \sum_{j=1}^n f(a_j) + \frac{m-a_i}{m-1} \left( \sum_{j \neq i}^n \left( \frac{a_j}{m-a_i} f(a_j-1) + \frac{m-a_i-a_j}{m-a_i} f(a_j) \right) + f(a_i+1) \right) \right) \\ &= \sum_{i=1}^n \frac{a_i}{m} \left( \frac{a_i-1}{m-1} \sum_{j=1}^n f(a_j) + \sum_{j \neq i}^n \left( \frac{a_j}{m-1} f(a_j-1) + \frac{m-a_i-a_j}{m-1} f(a_j) \right) + \frac{m-a_i}{m-1} f(a_i+1) \right) \\ &= \sum_{i=1}^n \frac{a_i}{m} \left( \frac{a_i-1}{m-1} f(a_i) + \frac{m-a_i}{m-1} f(a_i+1) + \sum_{j \neq i}^n \left( \frac{a_j}{m-1} f(a_j-1) + \frac{m-1-a_j}{m-1} f(a_j) \right) \right) \\ &= \frac{1}{m(m-1)} \sum_{i=1}^n \left( a_i(m-a_i)f(a_i+1) + a_i(m-a_i) f(a_i-1) + \left( a_i(a_i-1)+(m-a_i)(m-1-a_i) \right) f(a_i) \right) \\ \end{aligned} \]

\[-1 = \sum_{i=1}^n \frac{a_i(m-a_i)}{m(m-1)} \left( f(a_i+1) + f(a_i-1) - 2f(a_i) \right) \]

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

\[f(x+1) - f(x) = f(x) - f(x-1) -\frac{m-1}{m-x} \]

设 $ g(x) = f(x+1) - f(x) $

\[g(x) - g(x-1) = -\frac{m-1}{m-x} \]

关键在于求 $ f(m) $

\[ \begin{aligned} f(m) &= \sum_{i=0}^{m-1} \sum_{j=0}^i -\frac{m-1}{m-j} \\ &= \sum_{j=0}^{m-1} -(m-1) \\ &= -m(m-1) \\ \end{aligned} \]

code
#include <iostream>
#define Sakura int
#define Re register ll
#define _ putchar(' ')
#define el putchar('\n')
#define ll long long
#define fre(x,y) freopen(#x".in","r",stdin),freopen(#y".out","w",stdout);

using namespace std;

const ll maxn=2500+10;
const ll Maxn=1e5+10;
const ll mod=1e9+7;

inline ll read(){
    ll x=0,f=0;char c=getchar();
    while(!isdigit(c)) f|=c=='-',c=getchar();
    while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return f?-x:x;
}

inline void ot(ll x) {
    if(x<0) putchar('-'),x=-x;
    if(x>9) ot(x/10);putchar(x%10|48);
}

ll n,m;
ll a[maxn],Max;
ll f[Maxn],g[Maxn];
ll ans;

inline ll qpow(ll x,ll d) {
	ll res=1;
	while(d) {
		if(d&1) res=res*x%mod;
		x=x*x%mod;
		d>>=1;
	}
	return res;
}

Sakura main() {
	n=read();
	for(Re i=1;i<=n;++i) a[i]=read(),m+=a[i],Max=max(Max,a[i]);
	m%=mod;
	g[0]=-(m-1)*qpow(m,mod-2)%mod;
	for(Re i=1;i<=Max;++i) g[i]=(g[i-1]-(m-1)*qpow(m-i,mod-2))%mod,f[i]=(f[i-1]+g[i-1])%mod;
	for(Re i=1;i<=n;++i) (ans+=f[a[i]])%=mod;
	(ans+=m*(m-1))%=mod;
	if(ans<0) ans+=mod;
	ot(ans);
}
posted @ 2023-02-01 11:18  hzoi_Sakura  阅读(175)  评论(3编辑  收藏  举报