【NOI模拟赛】不知是哪一道CF的论文题(概率期望,鞅的停时定理)

题面

在这里插入图片描述
在这里插入图片描述

题解

论文:(看不懂的)彭博《鞅与一类关于停时的概率与期望问题》

鞅的邒时定理

鞅是一类特殊的随机过程,起源于对公平赌博游戏的数学描述。假设我们从一开始就在观察一场赌博游戏,现在已经得到了前 t t t 秒的观测值,那么当第 t + 1 t+1 t+1观测值的期望等于第 t t t 秒的观测值时,我们才称这是公平赌博游戏。

随机过程:在随机的背景下,时刻 i i i 会有状态 X i X_i Xi ,把它们依次记录下来就获得了随机过程。

:对于一个随机过程 { X 0 , X 1 , . . . } \{X_0,X_1,...\} {X0,X1,...} ,如果 E ( X n + 1 ∣ X 0 , X 1 , . . . , X n ) = X n E(X_{n+1}|X_0,X_1,...,X_n)=X_n E(Xn+1X0,X1,...,Xn)=Xn ,我们就称这个随机过程为鞅。

注: E ( X n + 1 ∣ X 0 , X 1 , . . . , X n ) E(X_{n+1}|X_0,X_1,...,X_n) E(Xn+1X0,X1,...,Xn) 是条件期望,且得保证期望状态的定义是存在且合理的。

停时定理:对于任意停时 t t t (在这个时间结束观测,在不知晓中间的随机过程时讨论停时状态的期望),有 E ( X t ) = X 0 E(X_t)=X_0 E(Xt)=X0

势能函数结论

考虑一个随机过程 { A 0 , A 1 , . . . } \{A_0,A_1,...\} {A0,A1,...},当确定终止状态为 A t A_t At 的时候,怎么求出停时 t t t 的期望 E ( t ) E(t) E(t) ,我们可以构造一个函数 Φ ( A ) \Phi(A) Φ(A) ,满足:

  • E ( Φ ( A n + 1 ) − Φ ( A n ) ∣ A 0 , A 1 , . . . , A n ) = − 1 E(\Phi(A_{n+1})-\Phi(A_n)|A_0,A_1,...,A_n)=-1 E(Φ(An+1)Φ(An)A0,A1,...,An)=1 ,势能随着时间期望减少。
  • Φ ( A t ) \Phi(A_t) Φ(At) 为常值,且 Φ ( A i ) = Φ ( A t ) \Phi(A_i)=\Phi(A_t) Φ(Ai)=Φ(At) 当且仅当 i = t i=t i=t ,末状态唯一对应一个势能。

通过构造 B i = Φ ( A i ) + i B_i=\Phi(A_i)+i Bi=Φ(Ai)+i ,可知 E ( B n + 1 ∣ B 0 , B 1 , . . . , B n ) = B n E(B_{n+1}|B_0,B_1,...,B_n)=B_n E(Bn+1B0,B1,...,Bn)=Bn ,所以 { B i } \{B_i\} {Bi} 也是一个鞅,根据停时定理,有 E ( B t ) = B 0   ⇒   E ( Φ ( A t ) + t ) = Φ ( A 0 )   ⇒   Φ ( A t ) + E ( t ) = Φ ( A 0 ) E(B_t)=B_0~\Rightarrow~E(\Phi(A_t)+t)=\Phi(A_0)~\Rightarrow~\Phi(A_t)+E(t)=\Phi(A_0) E(Bt)=B0  E(Φ(At)+t)=Φ(A0)  Φ(At)+E(t)=Φ(A0)

所以得到停时期望的计算方法 E ( t ) = Φ ( A 0 ) − Φ ( A t ) E(t)=\Phi(A_0)-\Phi(A_t) E(t)=Φ(A0)Φ(At)

回到这道屑题

(凑齐六字标题

我们定义状态 n n n 维向量,那么就可以合法地定义状态的期望,并惊喜地发现该随机过程是个

现在我们得定义一个势能函数 Φ ( A ⃗ ) \Phi(\vec{A}) Φ(A ) ,满足每次期望减少 1 。

不妨试试 Φ ( A ⃗ ) = ∑ f ( a i ) \Phi(\vec{A})=\sum f(a_i) Φ(A )=f(ai) ,令 m = ∑ a i m=\sum a_i m=ai m m m 是不变的),考察每一个 a i a_i ai f ( a i ) f(a_i) f(ai) 的变化,根据定义可得
∑ i = 1 n a i ( m − a i ) m ( m − 1 ) ( f ( a i + 1 ) − f ( a i ) + f ( a i − 1 ) − f ( a i ) ) = − 1 \sum_{i=1}^{n} \frac{a_i(m-a_i)}{m(m-1)}\left( f(a_i+1)-f(a_i)+f(a_i-1)-f(a_i) \right)=-1 i=1nm(m1)ai(mai)(f(ai+1)f(ai)+f(ai1)f(ai))=1

尝试构造一下?如果能变成 ∑ i = 1 n a i ( 1 − m ) m ( m − 1 ) \sum_{i=1}^{n}\frac{a_i(1-m)}{m(m-1)} i=1nm(m1)ai(1m) 该多好啊,令
( f ( a i + 1 ) − f ( a i ) ) − ( f ( a i ) − f ( a i − 1 ) ) = 1 − m m − a i \big(f(a_i+1)-f(a_i)\big)-\big(f(a_i)-f(a_i-1)\big)=\frac{1-m}{m-a_i} (f(ai+1)f(ai))(f(ai)f(ai1))=mai1m

看式子左边会发现非常的美观,令 h ( x ) h(x) h(x) f ( x ) f(x) f(x) 差分两次后的函数( ∑ i = 1 n h ( i ) = f ( n + 1 ) − f ( n ) \sum_{i=1}^{n}h(i)=f(n+1)-f(n) i=1nh(i)=f(n+1)f(n)),那么
h ( x ) = 1 − m m − x h(x)=\frac{1-m}{m-x} h(x)=mx1m

我们可以直接前缀和求出所有的 f ( a i ) f(a_i) f(ai) ,时间复杂度 O ( a log ⁡ P ) O(a\log P) O(alogP) ,但是我们还需要求出 f ( m ) f(m) f(m) ,直接递推的最高效求法时间和空间都是 O ( m ) O(m) O(m) 的,但是我们注意到这个下标它刚好等于 m m m ,可以有美妙的性质:
f ( m ) = ∑ i = 0 m − 1 ∑ j = 0 i 1 − m m − j = ∑ j = 0 m − 1 1 − m m − j ⋅ ( m − j ) = m ( 1 − m ) f(m)=\sum_{i=0}^{m-1}\sum_{j=0}^{i}\frac{1-m}{m-j}=\sum_{j=0}^{m-1}\frac{1-m}{m-j}\cdot (m-j) =m(1-m) f(m)=i=0m1j=0imj1m=j=0m1mj1m(mj)=m(1m)

震惊!竟只用一次乘法就能得出答案!

总时间复杂度 O ( a log ⁡ P ) O(a\log P) O(alogP)

CODE

#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<random>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#pragma GCC optimize(2)
using namespace std;
#define MAXN 100005
#define LL long long
#define ULL unsigned long long
#define ENDL putchar('\n')
#define DB double
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define PR pair<int,int>
#define UIN unsigned int
int xchar() {
	static const int maxn = 1000000;
	static char b[maxn];
	static int pos = 0,len = 0;
	if(pos == len) pos = 0,len = fread(b,1,maxn,stdin);
	if(pos == len) return -1;
	return b[pos ++];
}
// #define getchar() xchar()
inline LL read() {
	LL f = 1,x = 0;int s = getchar();
	while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
	while(s >= '0' && s <= '9') {x = (x<<1) + (x<<3) + (s^48);s = getchar();}
	return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar((x%10)^48);}
inline void putnum(LL x) {
	if(!x) {putchar('0');return ;}
	if(x<0) putchar('-'),x = -x;
	return putpos(x);
}
inline void AIput(LL x,int c) {putnum(x);putchar(c);}

const int MOD = 1000000007;
int n,m,s,o,k;
inline int qkpow(int a,int b) {
	int res = 1;
	while(b > 0) {
		if(b & 1) res = res *1ll* a % MOD;
		a = a *1ll* a % MOD; b >>= 1;
	} return res;
}
int a[MAXN];
int f[MAXN];
int main() {
	freopen("ball.in","r",stdin);
	freopen("ball.out","w",stdout);
	n = read(); m = 0;
	for(int i = 1;i <= n;i ++) a[i] = read(),m += a[i];
	for(int i = 1;i <= MAXN-5;i ++) {
		f[i] = (MOD+1-m) *1ll* qkpow(m-i+1,MOD-2) % MOD;
	}
	for(int i = 1;i <= MAXN-5;i ++) (f[i] += f[i-1]) %= MOD;
	for(int i = 1;i <= MAXN-5;i ++) (f[i] += f[i-1]) %= MOD;
	int ans = m*1ll*(m-1) % MOD;
	for(int i = 1;i <= n;i ++) {
		(ans += f[a[i]]) %= MOD;
	}
	AIput(ans,'\n');
	return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
NOI(全国青少年信息学奥林匹克竞模拟的测试数据是指用于评测参选手的程序的输入和对应的输出。测试数据是非常重要的,因为它决定了参选手的程序能否正确地解决问。 在NOI模拟中,测试数据具有以下特点: 1.充分覆盖:测试数据应涵盖各种可能的输入情况,包括边界条件和极端情况。通过提供不同的测试数据,可以考察选手对问的全面理解和解决能力。 2.随机性和均衡性:为了公平起见,测试数据应该是随机生成的,而不是针对某个特定算法或解法设计的。同时,测试数据应该是均衡的,即各种情况的概率应该大致相等,以避免偏向某些解法。 3.合理性和可行性:测试数据应该是合理和可行的,即符合目要求的输入数据,并且是选手能够通过编写程序来处理的。测试数据应该考虑到程序的限制和时间复杂度,以充分测试选手的编程能力。 NOI模拟的测试数据通常由经验丰富的考组负责生成。他们会根据目的要求和限制,设计出一组合理、充分、随机和均衡的测试数据,以确保参选手的程序在各种情况下都能正确运行,并且能通过性能测试。 总之,测试数据在NOI模拟中起到了至关重要的作用,它既考察了选手对问的理解和解决能力,又提高了选手编程的技巧和效率。同时,合理和恰当的测试数据也是公平竞的保证,确保每个参选手有相同的机会和条件进行竞争。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值