专栏文章
AT ARC202B Japanese "Knight's Tour"
AT_arc202_b题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miostcre
- 此快照首次捕获于
- 2025/12/03 00:34 3 个月前
- 此快照最后确认于
- 2025/12/03 00:34 3 个月前
每一步移动为 ,所以行的变化一定是每次 。
又因为每一行肯定需要能被走到,于是有 ,即 为奇数。
又因为每一行肯定需要能被走到,于是有 ,即 为奇数。
当 为奇数时,把这个行的顺序记录下来,就可以当作每一步移动是 了。
考虑把这个过程定向,因为每一个位置都会被恰好经过一次且最后会成环,所以可以知道每个位置一定有一个前驱一个后继。
又因为前驱后继的行数其实是确定的(当前行数 ),所以可以分开各个行间的连边情况最后考虑合并。
考虑行间连边会成什么形态,不难发现只有以下 种(变量都是表示的列数,在 意义下):
- 。
- 。
- 当 时,。
- 当 时,。
同时会发现我们只关心能不能遍历完所有的 ,因为能遍历到这些点根据限制也就能遍历到所有的点。
先来考虑 ,即 为奇数的情况。
行间连边的差距只会是 ,假设表示 会走到 ,记 。
可以知道所有 应当相同,为行间差距的和(即 的数量减掉 的数量),并且合法当且仅当 。
于是可以枚举 ,对应的方案数就是 。
接下来考虑 ,即 为偶数的情况。
依然记 。
此时会发现因为存在第 种情况的干扰, 或许并不是全部相同的了。
不过会发现:对于 递推的过程,会发现若 的奇偶性相同, 的变换量也是相同的。
于是可以知道,奇数的 的 一定相同,偶数的 的 一定相同。
于是可以知道,奇数的 的 一定相同,偶数的 的 一定相同。
考虑此时的 要满足什么限制:
- 。
- 。
- ,这个的意义是把 和 捆绑,当作是 ,要求所有偶数也得成一个环, 这个形式或许更直观。
发现因为 ,所以 ,所以前两个限制一定满足。
那么只需要考虑最后一个限制了,依然可以考虑枚举 的值,考虑计数。
发现能够把四种可能的情况分析为: 可以选择 , 可以选择 (任意一种情况的组合一定存在)。
于是可以看作是一个长度 的折线,每一步都是 ,最后值为 ,方案数就为 。
发现能够把四种可能的情况分析为: 可以选择 , 可以选择 (任意一种情况的组合一定存在)。
于是可以看作是一个长度 的折线,每一步都是 ,最后值为 ,方案数就为 。
时间复杂度为 ,因为涉及到求 。
实现中 为偶数的情况枚举的是 。
C// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using ll = long long;
constexpr ll mod = 998244353;
constexpr ll inv2 = (mod + 1) / 2;
inline ll qpow(ll a, ll b) {
ll v = 1;
for (; b; b >>= 1, a = a * a % mod) {
if (b & 1) v = v * a % mod;
}
return v;
}
constexpr int maxH = 4e5 + 10;
ll fac[maxH], ifac[maxH];
inline ll binom(int n, int m) {
return fac[n] * ifac[n - m] % mod * ifac[m] % mod;
}
int main() {
int H, W;
scanf("%d%d", &H, &W);
if (H % 2 == 0) return puts("0"), 0;
fac[0] = 1;
for (int i = 1; i <= H * 2; i++) {
fac[i] = fac[i - 1] * i % mod;
}
ifac[H * 2] = qpow(fac[H * 2], mod - 2);
for (int i = H * 2; i >= 1; i--) {
ifac[i - 1] = ifac[i] * i % mod;
}
ll ans = 0;
if (W % 2 == 1) {
for (int i = -H; i <= H; i += 2) {
if (std::__gcd(std::abs(i), W) != 1) continue;
(ans += binom(H, (H + i) / 2)) %= mod;
}
} else {
for (int i = -H; i <= H; i++) {
if (std::__gcd(std::abs(i), W / 2) != 1) continue;
(ans += binom(H * 2, H + i)) %= mod;
}
}
printf("%lld\n", ans);
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...