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;
}

浙公网安备 33010602011771号