AtCoder Regular Contest 191 (Div. 2)
ARC191A Replace Digits
除了最后一个字符必须在 \(s\) 中,其他字符都是随意的。
从高往低一次填即可,能填最后一个就填,否则就填前面的。
最后再把最后一个字符放到最后一个位置即可。
constexpr int N = 1e6 + 5;
int n, m, cnt[10], ans[N];
char s[N], t[N];
void slv() {
Read(n, m), Read(s), Read(t);
for (int i = 0; i + 1 < m; i ++)
++ cnt[t[i] - '0'];
int mx = 9; bool chs = false;
int lst = t[m - 1] - '0';
for (int i = 0; i < n; i ++) {
ans[i] = s[i] - '0';
while (mx >= 0 && !cnt[mx]) mx --;
if (mx > ans[i]) {
if (!chs && lst >= mx) {
ans[i] = lst, chs = true;
continue;
}
ans[i] = mx, cnt[mx] --;
} else if (!chs && lst > ans[i]) {
ans[i] = lst, chs = true;
}
}
if (!chs) {
for (int i = 0; i < n; i ++)
if (ans[i] <= lst) {
ans[i] = lst, chs = true;
break;
}
if (!chs) {
ans[n - 1] = lst;
}
}
for (int i = 0; i < n; i ++) Write(ans[i]);
return;
}
ARC191B XOR = MOD
首先 \(n \le x < 2n\),那么就是说我们只需要考虑 \(x - n = x \oplus n\) 的情况。
不难发现这其实就是在说二进制下 \(x\) 是 \(n\) 的超集。
void slv() {
int n, k; Read(n, k);
int len = __lg(n);
vector<int> bit;
for (int i = 0; i <= len; i ++)
if (!(n >> i & 1)) bit.emplace_back(i);
-- k;
if (1 << bit.size() <= k) {
Puts("-1");
return;
}
int ans = n;
for (int i = 0; i < bit.size(); i ++)
if (k >> i & 1) ans |= 1 << bit[i];
Write(ans, '\n');
return;
}
C - A^n - 1
构造 \((A, M) = (N + 1, N^2)\),正确性显然。
诗人?
D - Moving Pieces on Graph
就摁分讨,没营养。
懒得写了。
E - Unfair Game
发现每个袋子是几乎独立的,考虑一个袋子的情况。
发现能不能赢是只和奇偶性相关的,所以可以把 \((X, Y, A, B)\) 替换成 \((X \bmod 2, Y \bmod 2, A, B \bmod 2)\)。
进行分类讨论:
- 若 \(X = Y\),可以直接看 \(A \cdot (X + 1) + B\) 的奇偶性。
- 若 \(X = 0, Y = 1\),那么在 \(A \neq 0\) 时先手是有机会调节奇偶性的,之后只需要逼迫后手选金币就赢了。
- 若 \(X = 1, Y = 0\),如果 \(A > 1\) 和上面的是相同的,\(A \le 1\) 可以搜。
综上,在 \(X = Y\) 时,先手必胜当且仅当 \(A\cdot (X + 1) +B\) 是奇数;否则可以将 \((X, Y, A, B)\) 替换成 \((X \bmod 2, Y \bmod 2, \min(A, 2), B \bmod 2)\) 后爆搜。
对于多个袋子的情况,可以把每个袋子 \((A, B)\) 我们可以把它看成一个二元组 \((a, b)\),表示对于两个人来说是不是先手必胜的。
对于一个先手必胜的袋子,它的影响其实就是交换先后手。
所以假设 Takahashi 有 \(x\) 个先手必胜的袋子,Aoki 有 \(y\) 个先手必胜的袋子,那么 Takahashi 赢的充要条件就是 \(x >y\)。
如果记 \((a, b)\) 类型的袋子个数为 \(c_{a, b}\),那么方案数为:
那么就是要求 \(F(z) = \displaystyle (1+z)^A (1+z^2)^B\) 的各项系数。
其 ODE 是:
可以得到递推式:
时间复杂度线性。
bool win[2][2][3][2], vis[2][2][3][2];
void slv() {
int n, X, Y;
Read(n, X, Y);
X &= 1, Y &= 1;
auto chk = [&](auto self, int X, int Y, int A, int B) -> bool {
if (vis[X][Y][A][B]) {
return win[X][Y][A][B];
}
vis[X][Y][A][B] = true;
if (A != 0) {
if (!self(self, Y, X, A - 1, (B + X) & 1)) {
return win[X][Y][A][B] = true;
}
}
if (B != 0) {
if (!self(self, Y, X, A, B - 1)) {
return win[X][Y][A][B] = true;
}
}
return win[X][Y][A][B] = false;
};
array<array<int, 2>, 2> c;
c[0][0] = c[0][1] = c[1][0] = c[1][1] = 0;
for (int i = 0; i < n; i ++) {
int A, B; Read(A, B);
if (X == Y) {
int o = ((X + 1) * A + B) & 1;
++ c[o][o];
} else {
int o0 = chk(chk, X, Y, min(2, A), B & 1),
o1 = chk(chk, Y, X, min(2, A), B & 1);
++ c[o0][o1];
}
}
vector<mint> f(2 * n + 1);
int A = c[1][0] + c[0][1], B = c[1][1];
f[0] = 1, f[1] = A, f[2] = comb.C(A, 2) + B;
for (int i = 2; i < 2 * n; i ++) {
f[i + 1] += (A - i) * f[i];
f[i + 1] += (2 * B - i + 1) * f[i - 1];
f[i + 1] += (A + 2 * B - i + 2) * f[i - 2];
f[i + 1] *= comb.inv(i + 1);
}
mint ans = 0;
for (int i = c[0][1] + c[1][1] + 1; i <= 2 * n; i ++) {
ans += f[i];
}
while (c[0][0] --) {
ans *= 2;
}
Write((int)ans, '\n');
return;
}

浙公网安备 33010602011771号