AtCoder AGC073 A 题解

题目链接:https://atcoder.jp/contests/agc073/tasks/agc073_a

参考出题人题解

首先理解题意可以破圆为链,直接枚举肯定会超时,考虑将转化成期望,对于某一段黑色区域,当某区域包含一段弧时,我们给每个端点加上 \(\frac{1}{2}\) 的权值,当该区域不包含弧时,该区域存在一个距离圆心最远的唯一点,我们给该点加上 \(1\) 的权值,显然,对于一段弧来说,选中它的概率为 \(\frac{1}{2}\),并且对于一个弧来说,它附近的两个区域肯定是一黑一白,因此端点权重的期望为 \(\frac{1}{4}\)。对于两条弦的交点,首先,这两条弦都被选用的概率为 \(\frac{1}{4}\),其次,若不存在其他弦将圆心与该交点隔开,则该交点对应的区域始终为白色,权重恒为 \(0\)。反之,若存在一条或多条这样的弦,则有 \(\frac{1}{2}\) 的概率分配1的权重。综上,当无其他弦将交点与圆心隔开,期望值则为 \(0\),反之则为 \(\frac{1}{8}\)

计算总端点权值:每条弦有两个端点,每个端点的期望是 \(\frac{1}{4}\),因此总期望为 \(\frac{N}{2}\),但是对于两条的交点我们需要额外考虑,我们需要把端点带来的贡献先去掉。

假设共有 \(I\)个交点,显然所有交点的贡献便是 \(\frac{1}{8}I\)。对于没有交点的两弦来说,定义 \(V=\) 满足 \(Ai+k<=A_{i+1}\)\(i\) 的数量,那么无其他弦将其与圆心隔开的交点数量为 \(N-V\),剩下的 \(I-(N-V)\) 个交点有其他弦将其与圆心隔开。因此总交点期望便是 \((I-N+V)*\frac{1}{8}=\frac{1}{8}I-\frac{1}{8}N+\frac{1}{8}V\)

综上,总期望是 \(E=\frac{3}{8}N+\frac{1}{8}I+\frac{1}{8}V\),有 \(2^N\) 种可能,因此最后答案再乘以 \(2^N\) 即可。

代码如下:

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 4e5 + 10, mod = 998244353;
int a[N], l, k, n;
int ksm(int x, int y)
{
	int res = 1;
	while(y)
	{
		if(y & 1) res = res * x % mod;
		x = x * x % mod;
		y >>= 1;
	}
	return res;
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	int V = 0, I = 0;
	cin >> l >> k >> n;
	for(int i = 0; i < n; i++) cin >> a[i];
	for (int i = 0; i < n; i++) 
	{
        int val = (i == n - 1) ? a[0] + l : a[i + 1];
        if (a[i] + k <= val) V++;
    }
	// int j = 0;
	// for(int i = 0; i < n; i++)
	// {
	// 	while(j < n && a[j] <= a[i]) j++;
	// 	int h = j;
	// 	while(h < n && a[h] < a[i] + k) h++;
	// 	I += (h - j);
	// 	if(a[i] + k >= l)
	// 	{
	// 		int pos = a[i] + k - l;
	// 		int s = 0;
	// 		while(s < n && a[s] < pos)s++;
	// 		I += s;
	// 	}    
	// } 
	//  双指针被卡了
	for(int i = 0; i < n; i++)
	{
		if(a[i] + k < l)
		{
			int lf = upper_bound(a, a + n, a[i]) - a, rf = lower_bound(a, a + n, a[i] + k) - a;
			I += (rf - lf);
		}
		else
		{
			int lf = upper_bound(a, a + n, a[i]) - a, rf = lower_bound(a, a + n, a[i] + k - l) - a;
			I += (n - lf);
			I += rf;
		}
	}
	int inv = ksm(8, mod - 2);
	int e = (3ll * n + I + V) % mod;
	e = e * inv % mod;
	int num = ksm(2, n) % mod;
	int ans = e * num % mod;
	cout << ans;
}
posted @ 2025-09-29 20:38  turt1e  阅读(15)  评论(0)    收藏  举报