版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/83025412
【题目链接】
【思路要点】
- 一篇关于 的博客 。
- 考虑用 解决不平等博弈问题。
- 手动绘制转移图,计算出各个状态的 ,如下图。
- 令 ,实际上这也是 一文中 所建议的表示方式。
- 有如下事实,可由 的运算方式简单验证:
、 。
、 令 ,那么 。
、 令 ,那么 。
、 。
、 。
、 令 ,那么 。
、 令 ,那么 。
、 为先手必胜态。
、 。- 因此结论如下:
- 接下来唯一的问题是我们需要解决 的方案数。
- 第 的系数应当为 ,因此我们本质上只需要求出 个 的系数的前缀和,枚举 的一项,将 的系数前缀和即可。
- 时间复杂度 。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e6 + 5; const int P = 998244353; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int fac[MAXN], inv[MAXN], bit[MAXN]; int power(int x, int y) { if (y == 0) return 1; int tmp = power(x, y / 2); if (y % 2 == 0) return 1ll * tmp * tmp % P; else return 1ll * tmp * tmp % P * x % P; } int getc(int x, int y) { if (y > x) return 0; else return 1ll * fac[x] * inv[y] % P * inv[x - y] % P; } void init(int n) { fac[0] = bit[0] = 1; for (int i = 1; i <= n; i++) { fac[i] = 1ll * fac[i - 1] * i % P; bit[i] = bit[i - 1] * 2 % P; } inv[n] = power(fac[n], P - 2); for (int i = n - 1; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1ll) % P; } int n, m, cnt[8]; //0 : -1, 1 : -1/2, 2 : 0, 3 : 1/2, 4 : 1; //5 : *, 6 : up, 7 : down. void Loadinput() { read(n), m = 0; memset(cnt, 0, sizeof(cnt)); for (int i = 1; i <= n; i++) { string opt; int x; cin >> opt >> x; m += x; if (opt == "LL_RR") cnt[5] += x; if (opt == "L_LRR") cnt[6] += x; if (opt == "LLR_R") cnt[7] += x; if (opt == "_LLRR") cnt[2] += x; if (opt == "LRL_R") cnt[5] += x; if (opt == "L_RLR") cnt[5] += x; if (opt == "LLRR_") cnt[2] += x; if (opt == "LR_LR") cnt[2] += x; if (opt == "LRLR_") cnt[2] += x; if (opt == "_LRLR") cnt[2] += x; if (opt == "_RLLR") cnt[0] += x; if (opt == "LRRL_") cnt[4] += x; if (opt == "LR_RL") cnt[1] += x; if (opt == "RL_LR") cnt[3] += x; if (opt == "_RLRL") cnt[0] += x; if (opt == "LRR_L") cnt[2] += x; if (opt == "R_LLR") cnt[2] += x; if (opt == "RLRL_") cnt[4] += x; if (opt == "R_LRL") cnt[2] += x; if (opt == "RLR_L") cnt[2] += x; if (opt == "RRL_L") cnt[4] += x; if (opt == "R_RLL") cnt[0] += x; if (opt == "RR_LL") cnt[2] += x; } } int a[MAXN], b[MAXN], c[MAXN], sum[MAXN]; void work(int x, int y, int *a) { for (int i = 0; i <= x + y; i++) a[i] = getc(x + y, i); } void update(int &x, int y) { x += y; if (x >= P) x -= P; } int main() { init(1e6); int T, num; read(num), read(T); while (T--) { Loadinput(); int num[3] = {0, 0, 0}; // 0 : negative, 1 : zero, 2 : positive. work(cnt[0], cnt[4], a); work(cnt[1], cnt[3], b); work(cnt[7], cnt[6], c); for (int i = 1; i <= cnt[1] + cnt[3]; i++) update(b[i], b[i - 1]); num[2] = power(2, cnt[0] + cnt[1] + cnt[2] + cnt[3] + cnt[4]); for (int i = 0, j = cnt[1] + cnt[3], k = cnt[1] + cnt[3]; i <= cnt[0] + cnt[4]; i++) { while (j >= 0 && (i - cnt[0]) * 2 + (j - cnt[1]) >= 0) j--; while (k >= 0 && (i - cnt[0]) * 2 + (k - cnt[1]) > 0) k--; if (j >= 0) update(num[0], 1ll * a[i] * b[j] % P); if (k >= 0) update(num[1], 1ll * a[i] * b[k] % P); } num[0] = 1ll * num[0] * power(2, cnt[2]) % P; num[1] = 1ll * num[1] * power(2, cnt[2]) % P; update(num[2], P - num[1]); update(num[1], P - num[0]); int updown[5] = {0, 0, 0, 0, 0}; // 0 : less, 1 : -1, 2 : 0, 3 : 1, 4 : more. for (int i = 0; i <= cnt[6] + cnt[7]; i++) { int tmp = i - cnt[7]; if (tmp <= -2) update(updown[0], c[i]); if (tmp == -1) update(updown[1], c[i]); if (tmp == 0) update(updown[2], c[i]); if (tmp == 1) update(updown[3], c[i]); if (tmp >= 2) update(updown[4], c[i]); } int ans[4] = {0, 0, 0, 0}; ans[0] = 1ll * num[2] * power(2, cnt[5] + cnt[6] + cnt[7]) % P; ans[1] = 1ll * num[0] * power(2, cnt[5] + cnt[6] + cnt[7]) % P; if (cnt[5] == 0) { update(ans[0], 1ll * num[1] * (updown[3] + updown[4]) % P); update(ans[1], 1ll * num[1] * (updown[0] + updown[1]) % P); update(ans[3], 1ll * num[1] * updown[2] % P); } else { int tmp = power(2, cnt[5] - 1); update(ans[0], 1ll * tmp * num[1] % P * (updown[3] + updown[4]) % P); update(ans[1], 1ll * tmp * num[1] % P * (updown[0] + updown[1]) % P); update(ans[3], 1ll * tmp * num[1] % P * updown[2] % P); update(ans[0], 1ll * tmp * num[1] % P * updown[4] % P); update(ans[1], 1ll * tmp * num[1] % P * updown[0] % P); update(ans[2], 1ll * tmp * num[1] % P * (0ll + updown[1] + updown[2] + updown[3]) % P); } printf("%d %d %d %d\n", ans[0], ans[1], ans[2], ans[3]); } return 0; }