AGC073A - Chords and Checkered
关键词:计数的是被翻转了奇数次的区域个数;某
考虑染色操作的实质,其实是从一个全白的圆开始,然后每次我们选择一条弦围成的区域,将这块区域内颜色翻转,最后答案就是黑色区域个数。
那么对于一个区域,如果被翻转了奇数次,显然就是黑色,否则就是白色。所以实际上我们计数的是被翻转了奇数次的区域个数。
一个奇数次的区域分为两种情况,一种是只被翻转了
考虑只被翻转了
考虑被翻转了超过
所以做法就很明了了,记相交但是不连续(因为我们要使得
注意特判
#include <bits/stdc++.h>
using namespace std;
constexpr int N = 250010, P = 998244353;
inline int add(int x, int y) { if (x + y >= P) return x + y - P; return x + y; }
inline int sub(int x, int y) { if (x - y < 0) return x - y + P; return x - y; }
inline int mul(int x, int y) { return 1LL * x * y % P; }
inline void Add(int& x, int y) { x = add(x, y); }
inline void Sub(int& x, int y) { x = sub(x, y); }
inline void Mul(int& x, int y) { x = mul(x, y); }
inline int qpow(int x, int y = P - 2) {
int z = 1;
while (y) {
if (y & 1) z = mul(z, x);
x = mul(x, x);
y >>= 1;
}
return z;
}
int l, k, n, a[2 * N], ans;
int main() {
scanf("%d %d %d", &l, &k, &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), a[n + i] = a[i] + l;
ans = mul(n, qpow(2, n - 1));
int w = 0;
for (int i = n + 1, j = 0; i <= 2 * n; i++) {
if (j <= i - n) j = i - n + 1;
while (a[j] + k <= a[i]) j++;
int cnt = i - j;
if (cnt >= 1) Add(w, cnt - 1);
}
if (n >= 3) Add(ans, mul(w, qpow(2, n - 3)));
cout << ans << endl;
}