CodeForces 1187F Expected Square Beauty

本文探讨了在不确定数组条件下,求解特定函数平方期望值的复杂数学问题。通过定义随机变量并分析其性质,利用概率论原理,将问题转化为求随机变量的期望值。文章详细介绍了如何通过概率计算和组合数学技巧,高效地求解这一问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

Expected Square Beauty

题目大意

x x x是一个数列,定义函数 B ( x ) B(x) B(x)表示:将数列中连续的相同的作为一段的段数。例如 B ( [ 3 , 3 , 6 , 1 , 6 , 6 , 6 ] ) = 4 B([3,3,6,1,6,6,6])=4 B([3,3,6,1,6,6,6])=4,现在有一个 n n n个数的数组 a a a a i ∈ [ l i , r i ] a_i\in[l_i,r_i] ai[li,ri] a a a不确定,求 B ( a ) 2 B(a)^2 B(a)2的期望,期望是一个既约分数 p q \dfrac{p}{q} qp,输出 p ⋅ q − 1 m o d    1 0 9 + 1 p\cdot q^{-1}\mod 10^9+1 pq1mod109+1

分析

对于一个确定的数列 x x x x x x的长度为 n n n
B ( x ) B(x) B(x)和下面定义的 T ( i ) T(i) T(i)都是一个函数。
定义:若 x i ≠ x i + 1 x_i\neq x_{i+1} xi̸=xi+1 T ( i ) = 1 T(i)=1 T(i)=1,否则 T ( i ) = 0 T(i)=0 T(i)=0,并规定 T ( n ) = 1 T(n)=1 T(n)=1。显然 B ( x ) = ∑ i = 1 n T ( i ) B(x)=\sum\limits_{i=1}^{n}T(i) B(x)=i=1nT(i)
于是 B ( x ) 2 = ( ∑ i = 1 n T ( i ) ) 2 = ∑ i = 1 n ∑ j = 1 n [ T ( i ) T ( j ) ] B(x)^2=\left(\sum\limits_{i=1}^{n}T(i)\right)^2=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\left[T(i)T(j)\right] B(x)2=(i=1nT(i))2=i=1nj=1n[T(i)T(j)]


\\
对于不确定的数列 a a a
B ( a ) 2 B(a)^2 B(a)2和对应的 T ( i ) T(i) T(i)自然成了随机变量
所以我们要求的是这个随机变量的期望,即
E ( ∑ i = 1 n ∑ j = 1 n [ T ( i ) T ( j ) ] ) E\left(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\left[T(i)T(j)\right]\right) E(i=1nj=1n[T(i)T(j)])
由于期望可以加和,我们要求的变为了
∑ i = 1 n ∑ j = 1 n E ( T ( i ) T ( j ) ) \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}E(T(i)T(j)) i=1nj=1nE(T(i)T(j))

分两类讨论:

  • T ( i ) T ( j ) = 1 T(i)T(j)=1 T(i)T(j)=1时,意味着 a i a_i ai a i + 1 a_{i+1} ai+1不一样,并且 a j a_j aj a j + 1 a_{j+1} aj+1不一样
  • T ( i ) T ( j ) = 0 T(i)T(j)=0 T(i)T(j)=0时,即 T ( i ) = 0 T(i)=0 T(i)=0 T ( j ) = 0 T(j)=0 T(j)=0或都等于 0 0 0,表示的意义见定义

第二种情况对期望的贡献为 0 0 0,不用考虑,只考虑第一种情况对期望的贡献: 1 × P ( T ( i ) T ( j ) = 1 ) = P ( T ( i ) T ( j ) = 1 ) 1\times P(T(i)T(j)=1)=P(T(i)T(j)=1) 1×P(T(i)T(j)=1)=P(T(i)T(j)=1) P ( T ( i ) T ( j ) = 1 ) P(T(i)T(j)=1) P(T(i)T(j)=1) T ( i ) T ( j ) = 1 T(i)T(j)=1 T(i)T(j)=1发生的概率)
于是问题又变为了求 ∑ i = 1 n ∑ j = 1 n P ( T ( i ) T ( j ) = 1 ) \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}P(T(i)T(j)=1) i=1nj=1nP(T(i)T(j)=1)
换句话说,如果事件 f ( i ) f(i) f(i)表示 T ( i ) = 1 T(i)=1 T(i)=1,我们要求 ∑ i = 1 n ∑ j = 1 n P ( f ( i ) f ( j ) ) \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}P(f(i)f(j)) i=1nj=1nP(f(i)f(j)) P ( f ( i ) f ( j ) ) P(f(i)f(j)) P(f(i)f(j))表示的是 T ( i ) = 1 T(i)=1 T(i)=1 T ( j ) = 1 T(j)=1 T(j)=1这两件事同时发生的概率)


  • 显然 ∣ i − j ∣ ≥ 2 |i-j|\geq 2 ij2时, f ( i ) f(i) f(i) f ( j ) f(j) f(j)相互独立,则 P ( f ( i ) f ( j ) ) = P ( f ( i ) ) ⋅ P ( f ( j ) ) P(f(i)f(j))=P(f(i))\cdot P(f(j)) P(f(i)f(j))=P(f(i))P(f(j)),又因为 P ( f ( i ) ) = P ( a i 和 a i + 1 不 同 ) = 1 − P ( a i 和 a i + 1 相 同 同 ) = ∣ [ l i , r i ] ∩ [ l i + 1 , r i + 1 ] ∣ ( r i − l i + 1 ) ( r i + 1 − l i + 1 + 1 ) ( 1 ≤ i ≤ n ) P(f(i))=P(a_i和a_{i+1}不同)=1-P(a_i和a_{i+1}相同同)=\dfrac{|[l_i,r_i]\cap[l_{i+1},r_{i+1}]|}{(r_i-l_i+1)(r_{i+1}-l_{i+1}+1)}(1\leq i\leq n) P(f(i))=P(aiai+1)=1P(aiai+1)=(rili+1)(ri+1li+1+1)[li,ri][li+1,ri+1](1in)所以此时 P ( f ( i ) f ( j ) ) P(f(i)f(j)) P(f(i)f(j))可以求。

  • 如果 ∣ i − j ∣ = 1 |i-j|=1 ij=1 i i i j j j相邻, f ( i ) f(i) f(i) f ( i ) f(i) f(i)就相互有影响(想不清楚为什么有影响就再看 f ( i ) f(i) f(i) T ( i ) T(i) T(i)的定义)了,但是 P ( f ( i ) f ( j ) ) P(f(i)f(j)) P(f(i)f(j))容斥一下也不难算:不妨设 j = i + 1 j=i+1 j=i+1,则 P ( f ( i ) f ( j ) ) = P ( f ( i ) f ( i + 1 ) ) = 1 − P ( a i 和 a i + 1 相 同 ) − P ( a i + 1 和 a i + 2 相 同 ) + P ( a i 和 a i + 1 和 a i + 2 相 同 ) P(f(i)f(j))=P(f(i)f(i+1))=1-P(a_i和a_{i+1}相同)-P(a_{i+1}和a_{i+2}相同)+P(a_i和a_{i+1}和a_{i+2}相同) P(f(i)f(j))=P(f(i)f(i+1))=1P(aiai+1)P(ai+1ai+2)+P(aiai+1ai+2)所以此时 P ( f ( i ) f ( j ) ) P(f(i)f(j)) P(f(i)f(j))也可以求。

  • 如果 i = j i=j i=j,显然 P ( f ( i ) f ( j ) ) = P ( f ( i ) ) P(f(i)f(j))=P(f(i)) P(f(i)f(j))=P(f(i))


这样看来是 O ( n 2 ) O(n^2) O(n2)的,但是,对于每个 i i i,所有的满足 i − j ≥ 2 i-j\geq 2 ij2 P ( f ( j ) ) P(f(j)) P(f(j))可以用前缀和处理,然后根据分配率一起乘 P ( f ( i ) ) P(f(i)) P(f(i)) j − i ≥ 2 j-i\geq 2 ji2也可以算,这样一来就变成 O ( 1 ) O(1) O(1)啦。

代码

关于分数的处理,我写了分数结构体,分数的加减乘时分子和分母随时都可以取模,原因如下:

  • 分子显然可以取模。
  • 对于分母,最后是以逆元的形式输出,由于逆元是根据费马小定理求的,所以 m − 1 % p = m p − 1 % p m^{-1}\%p=m^{p-1}\%p m1%p=mp1%p,又因为 m p − 1 % p = ( m % p ) p − 1 % p m^{p-1}\%p=(m\%p)^{p-1}\%p mp1%p=(m%p)p1%p,所以 m − 1 % p = ( m % p ) − 1 % p m^{-1}\%p=(m\%p)^{-1}\%p m1%p=(m%p)1%p,故分母取模对逆元无影响。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define MAXN 200000
#define LL long long
#define MOD 1000000007
int N;
LL L[MAXN+5],R[MAXN+5];

LL Pow(LL x,LL y){
	LL ret=1ll;
	while(y){
		if(y&1)
			ret=(ret*x)%MOD;
		y>>=1;
		x=(x*x)%MOD;
	}
	return ret;
}
LL Inv(LL x){
	return Pow(x,MOD-2);
}

struct Fraction{
	LL A,B;
	Fraction(){A=0;B=1;}
	Fraction(int a,int b):
		A(a),B(b){}
	Fraction operator + (Fraction m){
		return Fraction((A*m.B%MOD+B*m.A%MOD)%MOD,B*m.B%MOD);
	}
	Fraction operator - (Fraction m){
		return Fraction(((A*m.B%MOD-B*m.A%MOD)%MOD+MOD)%MOD,B*m.B%MOD);
	}
	Fraction operator * (Fraction m){
		return Fraction(A*m.A%MOD,B*m.B%MOD);
	}
}F[MAXN+5],G[MAXN+5],Sum[MAXN+5];
//F[i]是f(i)的概率
//G[i]是f(i)和f(i+1)同时发生的概率
//Sum[i]=F[1]+...+F[i]

LL I(int L1,int R1,int L2,int R2){//求交集的大小
	return max(0,min(R1,R2)-max(L1,L2)+1);
}

int main(){
	scanf("%d",&N);
	for(int i=1;i<=N;i++)
		scanf("%lld",&L[i]);
	for(int i=1;i<=N;i++)
		scanf("%lld",&R[i]);
	for(int i=1;i<=N;i++){
		F[i]=Fraction(1,1)-
			 Fraction(I(L[i],R[i],L[i+1],R[i+1])%MOD,
					 (R[i]-L[i]+1)*(R[i+1]-L[i+1]+1)%MOD);
		Sum[i]=Sum[i-1]+F[i];
	}
	for(int i=1;i<=N-1;i++){
		LL All=(R[i]-L[i]+1)*(R[i+1]-L[i+1]+1)%MOD*(R[i+2]-L[i+2]+1)%MOD;
		G[i]=Fraction(1,1)-
			 Fraction(I(L[i],R[i],L[i+1],R[i+1])*(R[i+2]-L[i+2]+1)%MOD,All)-
			 Fraction(I(L[i+1],R[i+1],L[i+2],R[i+2])*(R[i]-L[i]+1)%MOD,All)+
			 Fraction(I(max(L[i],L[i+1]),min(R[i],R[i+1]),L[i+2],R[i+2]),All);
	}
	Fraction Ans(0,1);
	for(int i=1;i<=N;i++){
		if(i>1){
			Ans=Ans+F[i]*Sum[i-2];
			Ans=Ans+G[i-1];
		}
		if(i<N){
			Ans=Ans+F[i]*(Sum[N]-Sum[i+1]);
			Ans=Ans+G[i];
		}
		Ans=Ans+F[i];
	}
	//不需要约分
	printf("%lld",Ans.A*Inv(Ans.B)%MOD);
}
Codeforces 2123F 问题中,目标是通过重新排列数组 $ a $ 来最小化不动点的数量。所谓“不动点”是指在重新排列后的数组中满足 $ a_i = i $ 的位置。该问题要求设计一种策略,以最优方式重新排列数组元素,使得这样的不动点数量最少。 为了解决这个问题,可以采用贪心算法和图论思想相结合的策略: - 首先,观察到如果某个值 $ i $ 出现了多次(即 $ a_i = i $),那么这些重复的值必须被移动到其他位置,以消除不动点。 - 对于那些没有出现在其索引上的值(例如 $ a_i \neq i $),可以通过交换操作将其移动到合适的位置,从而避免产生新的不动点。 一个有效的解决方案可以基于以下步骤: 1. 构建一个映射表,记录每个值出现的位置。 2. 找出所有当前值等于其索引的位置(即当前的不动点)。 3. 尝试通过交换来消除这些不动点。优先考虑将这些值移动到未被占用的位置,并确保不会引入新的不动点。 4. 在无法完全消除所有不动点的情况下,选择最优的交换策略以尽可能减少不动点的数量。 以下是 Python 中的一个示例实现,用于解决此类问题的基本思路: ```python def minimize_fixed_points(n, a): pos = {} fixed_points = [] # 记录每个值的出现位置,并找出初始的不动点 for i in range(n): if a[i] == i + 1: fixed_points.append(i) if a[i] not in pos: pos[a[i]] = [] pos[a[i]].append(i) # 如果没有重复的值,则可以直接交换以消除所有不动点 result = a[:] for i in fixed_points: found = False for val in pos: if val != i + 1 and len(pos[val]) > 0: j = pos[val].pop() result[i], result[j] = result[j], result[i] found = True break if not found: # 特殊情况处理:当只剩下一个值时 for j in range(n): if j != i and result[j] != j + 1: result[i], result[j] = result[j], result[i] break return result # 示例输入 n = int(input()) a = list(map(int, input().split())) result = minimize_fixed_points(n, a) print(' '.join(map(str, result))) ``` 此代码实现了上述逻辑,并尝试通过交换来最小化不动点的数量。对于大多数情况,它能够有效消除所有不动点;在某些特殊情况下(例如所有值都唯一且存在多个不动点),则需要特别处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值