【Codeforces1187F】Expected Square Beauty

题目链接:

【Codeforces1187F】Expected Square Beauty

题目描述:

有一个长度为 $ n $ 的数列,第 $ i $ 个数的取值范围为 $ [l_i, r_i] $ ,定义一个数列的价值为这个数列极长连续相同段的个数,求一个数列价值的平方期望,对 $ 10^9 + 7 $ 取模 。
$ n leq 200000 $ 。

做法:

定义 $ F(x) $ 为数列的价值, $ I_i(x) $ 为数列中第 $ i $ 项与第 $ i - 1 $ 项是否不同 $ (I_i(x) = [x_i eq x_{i - 1}]) $ ,则有 $ F(x) = sum_{i = 1}^{n} I_i(x) $ 。

[E(B(x)^2) = E(sum_{i = 1}^{n}I_i(x)sum_{j = 1}^{n}I_j(x))\ = E(sum_{i = 1}^{n}sum_{j = 1}^{n}I_i(x)I_j(x))\ = sum_{i = 1}^{n}sum_{j = 1}^{n}E(I_i(x)I_j(x)) ]

考虑计算 $ E(I_i(x)I_j(x)) $ ,分三种情况考虑。
当 $ i = j $ 时, $ E(I_i(x)I_j(x)) = E(I_i(x)) $ 。
当 $ | i - j | > 1 $ 时, $ I_i(x), I_j(x) $ 互不影响, $ E(I_i(x)I_j(x)) = E(I_i(x))E(I_j(x)) $ 。
当 $ | i - j | = 1 $ 时,仅考虑 $ j = i + 1 $ 的贡献( $ i = j + 1 $ 同理)。$ E(I_i(x) I_j(x)) = P(x_{i - 1} eq x_{i} land x_{i} eq x_{i + 1}) $ 。考虑容斥, $ E(I_i(x) I_j(x)) = 1 - p_{i} - p_{i + 1} + P(x_{i - 1} = x_{i} land x_{i} = x_{i + 1}) $ ,就可以计算了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 200010;
int n, l[N], r[N], inv[N], ans;
int e[N], pre[N], suf[N];

inline int add(const int &x, const int &y) {
	return x + y < mod ? x + y : x + y - mod;
}
inline int sub(const int &x, const int &y) {
	return x - y < 0 ? x - y + mod : x - y;
}
inline int mul(const int &x, const int &y) { return (int)((ll)x * y % mod); }
int ksm(int x, int y = mod - 2) {
	int ss = 1; for(; y; y >>= 1, x = mul(x, x)) if(y & 1) ss = mul(ss, x);
	return ss;
}
int calc(int x, int y, int z) {
	if(!x) return 0;
	int w = min(min(r[y], r[x]), r[z]) - max(max(l[y], l[x]), l[z]) + 1;
	if(w < 0) w = 0;
	int val = mul(mul(inv[x], inv[y]), inv[z]); return mul(w, val);
}
int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%d", &l[i]);
	for(int i = 1; i <= n; i++) scanf("%d", &r[i]);
	e[1] = 1, inv[1] = ksm(r[1] - l[1] + 1);
	for(int i = 2; i <= n; i++) {
		inv[i] = ksm(r[i] - l[i] + 1);
		e[i] = min(r[i], r[i - 1]) - max(l[i], l[i - 1]) + 1;
		if(e[i] < 0) e[i] = 0;
		e[i] = mul(e[i], mul(inv[i - 1], inv[i])), e[i] = sub(1, e[i]);
	}
	for(int i = 1; i <= n; i++) pre[i] = add(pre[i - 1], e[i]);
	for(int i = n; i >= 1; i--) suf[i] = add(suf[i + 1], e[i]);
	for(int i = 1; i <= n; i++) {
		if(i < n) ans = add(ans, mul(e[i], suf[i + 2]));
		if(i > 1) ans = add(ans, mul(e[i], pre[i - 2]));
	}
	for(int i = 1; i <= n; i++) ans = add(ans, e[i]);
	for(int i = 1; i < n; i++) {
		int sum = sub(1, add(sub(1, e[i + 1]), sub(1, e[i])));
		sum = add(sum, calc(i - 1, i, i + 1));
		ans = add(ans, add(sum, sum));
	}
	printf("%d
", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/daniel14311531/p/11133122.html