AC475A 2024省选联测26 博弈
题意
两个人在一张 DAG 上移动棋子,每个格子的颜色为黑/白。
每次操作可以移动一个格子颜色和自己相同的棋子。
不能走的人输掉游戏。
先手为白色,问所有放棋子的 \(2 ^ n\) 种方案,先手必胜有多少。
Sol
不难发现,自己颜色内的棋子不会被对方偷走,也就是说,想控制所有棋子使得对方判负,相当于比对方走到自己颜色多 \(k\) 步。
注意到对于每一个棋子放的格子来说,都有最优方案。
所以考虑算出每个棋子能对先手多多少步。
然后对这个做 \(0/1\) 背包即可。
注意负数情况。
Code
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <array>
#define int long long
using namespace std;
#ifdef ONLINE_JUDGE
/* #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
*/
/* char buf[1 << 23], *p1 = buf, *p2 = buf, ubuf[1 << 23], *u = ubuf; */
#endif
int read() {
int p = 0, flg = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')
flg = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
p = p * 10 + c - '0';
c = getchar();
}
return p * flg;
}
void write(int x) {
if (x < 0) {
x = -x;
putchar('-');
}
if (x > 9) {
write(x / 10);
}
putchar(x % 10 + '0');
}
const int N = 305, M = 6e4 + 5, mod = 998244353;
namespace G {
array<int, N> fir;
array<int, M> nex, to;
int cnt = 1;
void add(int x, int y) {
cnt++;
nex[cnt] = fir[x];
to[cnt] = y;
fir[x] = cnt;
}
} // namespace G
char strbuf[N];
array<int, N> f;
void dfs(int x) {
if (~f[x])
return;
f[x] = 0;
for (int i = G::fir[x]; i; i = G::nex[i]) {
dfs(G::to[i]);
if (strbuf[x] == 'W')
f[x] = max(f[G::to[i]] + 1, f[x]);
else
f[x] = min(f[G::to[i]] - 1, f[x]);
}
}
void Mod(int &x) {
if (x >= mod)
x -= mod;
if (x < 0)
x += mod;
}
array<int, 2 * N * N> g;
signed main() {
freopen("game.in", "r", stdin);
freopen("game.out", "w", stdout);
int n = read(), m = read();
scanf("%s", strbuf + 1);
f.fill(-1);
for (int i = 1; i <= m; i++) {
int x = read(), y = read();
G::add(x, y);
}
for (int i = 1; i <= n; i++) dfs(i);
g[n * n] = 1;
for (int i = 1; i <= n; i++)
if (f[i] >= 0)
for (int j = 2 * n * n; j >= f[i]; j--) g[j] += g[j - f[i]], Mod(g[j]);
else
for (int j = 0; j <= 2 * n * n + f[i]; j++) g[j] += g[j - f[i]], Mod(g[j]);
int ans = 0;
for (int i = n * n + 1; i <= 2 * n * n; i++) ans += g[i], Mod(ans);
write(ans), puts("");
return 0;
}