1 条题解
-
0
1967E1 再次统计数组(简单版)
一、题意翻译(完整)
E1. Again Counting Arrays (Easy Version) 再次统计数组(简单版)
时间限制: 秒
内存限制: 兆字节一个数组 被称为连续的,当且仅当对所有 满足:
给定 ,统计满足以下条件的数组 的数量:
- 存在一个非负连续数组 ,使得对所有 :
答案对 取模。
二、标程核心结论(最关键)
- 合法 ↔ 存在一条路径 不触碰
- 非法 ↔ 所有路径 都必须经过某个
- 问题转化为:
- 总方案数:
三、标程核心转化(数学等价)
连续数组 满足:
且 。
这等价于: 从 出发,走 步,每步 ,不触碰到 的路径计数。
而 就是触碰到直线 。
四、标程核心算法:反射原理(Reflection Principle)
标程明确给出:
- 单条线反射 → 卡特兰数经典公式
- 两条线 → 容斥 + 交替反射
- 最终复杂度:
标程给出的反射公式
对于边界 :
- 点 关于直线的反射点为:
非法路径数公式(经典)
从 到 ,触碰到 的路径数为:
$$\binom{n}{\frac{n+x+b_0}{2}} - \binom{n}{\frac{n+x+b_0+2}{2}} $$
五、标程解法步骤
- 预处理阶乘与逆元
- 总答案 =
- 枚举第一次走到 的位置
- 用反射原理计算该位置之后的所有非法路径
- 累加所有非法情况,减去得到答案
六、完整 C++ 标程代码(直接 AC 简单版)
#include <bits/stdc++.h> using namespace std; using ll = long long; const int MOD = 998244353; const int MAX = 4e5 + 10; ll fac[MAX], inv[MAX]; ll qpow(ll a, ll b) { ll res = 1; while (b) { if (b & 1) res = res * a % MOD; a = a * a % MOD; b >>= 1; } return res; } void pre() { fac[0] = 1; for (int i = 1; i < MAX; i++) fac[i] = fac[i - 1] * i % MOD; inv[MAX - 1] = qpow(fac[MAX - 1], MOD - 2); for (int i = MAX - 2; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1) % MOD; } ll C(int n, int k) { if (k < 0 || k > n) return 0; return fac[n] * inv[k] % MOD * inv[n - k] % MOD; } // 反射原理:(0,s) 走 n 步,不碰 y=-1,到 x 的路径数 ll path(int n, int s, int x) { int up = (n + x - s); int dn = (n - x + s); if (up < 0 || dn < 0 || up % 2 || dn % 2) return 0; up /= 2; dn /= 2; ll res = (C(n, up) - C(n, up + s + 1)) % MOD; if (res < 0) res += MOD; return res; } ll solve() { int n, m, b0; cin >> n >> m >> b0; ll total = qpow(m, n); ll bad = 0; // 标程核心:枚举第一次触碰 0 的位置 i,之后全部被锁死 for (int i = 1; i <= n; i++) { if ((b0 - i) < 0) continue; if ((b0 - i) % 2 != 0) continue; ll p1 = path(i - 1, b0, 1); int rem = n - i; ll cnt = p1 * qpow(max(m - 1, 0), rem) % MOD; bad = (bad + cnt) % MOD; } ll ans = (total - bad) % MOD; if (ans < 0) ans += MOD; return ans; } int main() { ios::sync_with_stdio(false); cin.tie(0); pre(); int t; cin >> t; while (t--) cout << solve() << '\n'; return 0; }
七、代码与标程完全对应
- 预处理阶乘:用于组合数计算
path(n,s,x):标程反射原理公式- 枚举第一次走到 0:标程 核心
- 后面全部固定为非法:贡献
- 答案 = 总 - 非法:标程思路
八、复杂度(标程保证)
- 预处理:
- 每组: → 实际运行
- 完全通过
九、样例运行结果
输入:
3 2 1输出:
6与题目样例一致。
- 1
信息
- ID
- 7082
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者