# AtCoder Grand Contest 045

## A - Xor Battle

$X_{N + 1} = \{0\}$。如果 $S_i = \mathtt{0}$$X_i = X_{i + 1} \oplus A_i$；否则如果 $A_i \notin X_{i + 1}$$X_i = \varnothing$ 否则 $X_i = X_{i + 1}$

#include <cstdio>

typedef long long LL;
const int MN = 205;

int N;
LL A[MN];
char s[MN];
LL B[64];

int main() {
int Tests;
scanf("%d", &Tests);
while (Tests--) {
scanf("%d", &N);
for (int i = 1; i <= N; ++i) scanf("%lld", &A[i]);
scanf("%s", s + 1);
int ok = 1;
for (int j = 0; j < 60; ++j) B[j] = 0;
for (int i = N; i >= 1; --i) {
if (s[i] == '1') {
LL x = A[i];
for (int j = 59; j >= 0; --j) if (x >> j & 1) {
if (B[j]) x ^= B[j];
else break;
}
if (x) { ok = 0; break; }
} else {
LL x = A[i];
for (int j = 59; j >= 0; --j) if (x >> j & 1) {
if (!B[j]) B[j] = x;
x ^= B[j];
}
}
}
puts(ok ? "0" : "1");
}
return 0;
}


## B - 01 Unbalanced

#include <cstdio>
#include <cstring>
#include <algorithm>

const int MN = 1000005;

int N;
char S[MN];

int p[MN];
inline int Solve(int lb) {
p[N] = 0;
for (int i = N; i >= 1; --i)
p[i - 1] = std::max(p[i] + (S[i] == '1' ? 1 : -1), 0);
int maxval = 0;
for (int i = 1, now = 0; i <= N; maxval = std::max(maxval, now), ++i)
if (S[i] == '?') now += now - 1 - p[i] >= lb ? -1 : 1;
else now += S[i] == '0' ? 1 : -1;
return maxval;
}

int main() {
scanf("%s", S + 1), N = strlen(S + 1);
int minval = 0;
for (int i = 1, now = 0; i <= N; ++i)
if (S[i] == '1') minval = std::min(minval, --now);
else ++now;
printf("%d\n", std::min(Solve(minval) - minval, Solve(minval - 1) - minval + 1));
return 0;
}


## C - Range Set

#include <cstdio>
#include <algorithm>

typedef long long LL;
const int Mod = 1000000007;
const int MN = 5005;

inline int qPow(int b, int e) {
int a = 1;
for (; e; e >>= 1, b = (LL)b * b % Mod)
if (e & 1) a = (LL)a * b % Mod;
return a;
}

int N, A, B;
int f1[MN], f2[MN], f3[MN], f4[MN];
int g1[MN], g2[MN];

int main() {
scanf("%d%d%d", &N, &A, &B);
if (A > B) std::swap(A, B);
if (A == 1) return printf("%d\n", qPow(2, N)), 0;
f1[1] = 1;
for (int i = 2; i < B; ++i) {
f1[i] = 1;
for (int j = 1; j <= i - 1; ++j)
f1[i] = (f1[i] + f2[i - j]) % Mod;
for (int j = A; j <= i - 1; ++j)
f2[i] = (f2[i] + f1[i - j]) % Mod;
for (int j = 1; j <= i - 1; ++j)
f3[i] = (f3[i] + f4[i - j]) % Mod;
if (i >= A) f4[i] = 1;
for (int j = A; j <= i - 1; ++j)
f4[i] = (f4[i] + f3[i - j]) % Mod;
}
for (int i = 1; i <= N; ++i) {
if (i < B) g1[i] = (f1[i] + f3[i]) % Mod;
for (int j = 1; j < B && j <= i - 1; ++j)
g1[i] = (g1[i] + (LL)g2[i - j] * f1[j]) % Mod;
if (i < A) g2[i] = 1;
for (int j = 1; j < A && j <= i - 1; ++j)
g2[i] = (g2[i] + g1[i - j]) % Mod;
}
int Ans = (g1[N] + g2[N]) % Mod;
for (int j = 1; j <= N - 1; ++j)
Ans = (Ans + (LL)g2[N - j] * f2[j]) % Mod;
printf("%d\n", (qPow(2, N) - Ans + Mod) % Mod);
return 0;
}


## D - Lamps and Buttons

1. 随便选取一盏还不知道 $p_i$ 的值为多少的，现在还亮着的 $i$ 号灯。那么状态变化的灯的编号为 $p_i$
• 如果不存在这样的灯，则说明所有灭着的灯无法被点亮，输掉游戏。
• 如果选完之后它自己灭掉了（$p_i = i$），那就输掉了游戏。
2. 容易发现，此时 $i$ 所在循环长度 $\ge 2$，可以按顺序依次确定 $p_{p_i}, p_{p_{p_i}}$ 等等，然后把它们全部点亮。
3. 如果此时所有灯都被点亮了，Snuke 就赢了，否则回到步骤 1。

1. 对于 $1 \le i < t$，满足 $p_i \ne i$
2. 如果 $t \le A$，满足 $p_t = t$
3. 如果 $t \le A$，对于 $t < k \le A$，这部分不需要满足任何特殊条件。
4. 对于 $A < j \le N$，满足它所在的循环中至少存在一个满足 $1 \le i < t$ 的元素 $i$

$a$ 个任意置换方案数为 $a!$，依次加入后 $b$ 个，必须要插入在已存在的循环内，若当前是第 $i$ 个，则有 $(a + i - 1)$ 种方案。

#include <cstdio>

typedef long long LL;
const int Mod = 1000000007;
const int MN = 10000005, MA = 5005;

inline int qPow(int b, int e) {
int a = 1;
for (; e; e >>= 1, b = (LL)b * b % Mod)
if (e & 1) a = (LL)a * b % Mod;
return a;
}

int Fac[MN], iFac[MN], Inv[MN];
inline void Init(int N) {
Fac[0] = 1;
for (int i = 1; i <= N; ++i) Fac[i] = (LL)Fac[i - 1] * i % Mod;
iFac[N] = qPow(Fac[N], Mod - 2);
for (int i = N; i >= 1; --i) iFac[i - 1] = (LL)iFac[i] * i % Mod;
for (int i = 1; i <= N; ++i) Inv[i] = (LL)iFac[i] * Fac[i - 1] % Mod;
}
inline int Binom(int N, int M) {
return (LL)Fac[N] * iFac[M] % Mod * iFac[N - M] % Mod;
}

int N, A;

int main() {
scanf("%d%d", &N, &A);
Init(N);
int Ans = 0;
for (int t = 2; t <= A + 1; ++t) {
int a = t - 1, b = N - A, c = t <= A ? A - t : 0;
for (int d = 0; d <= a; ++d)
Ans = (Ans + (d & 1 ? -1ll : 1ll) * Binom(a, d) * Fac[a - d + b + c] % Mod * (a - d) % Mod * Inv[a - d + b]) % Mod;
}
printf("%d\n", (Ans + Mod) % Mod);
return 0;
}


## F - Division into Multiples

posted @ 2020-06-09 02:00  粉兔  阅读(162)  评论(0编辑  收藏