ARC223B Valid Arrays by K-Divisible Swaps
个人记录第二十四篇。
题意
给你一个长为 \(n\) 的正整数序列 \(A=\{a_1,a_2,a_3,\dots,a_n\}\) 和一个正整数 \(K\)。你可以对 \(A\) 进行任意次(可以为 \(0\) 次)操作,具体如下:
- 选择 \(i\in[1,n-1]\),如果 \(a_i+a_{i+1}\) 可以被 \(K\) 整除,则将其交换。
问你在若干次操作后可以得到的 \(A\) 的数量,答案对 \(998244353\) 取模。
解法
显然,\(a_i\) 和 \(a_{i+1}\) 能够交换,当且仅当 \((a_i+a_{i+1})\mod K=0\)。令 \(r_i=a_i\mod K\),那么可以得到 \(r_i+r_{i+1}\equiv0\pmod K\)。
所以我们考虑通过这类余数进行分段,满足 \(r_i+r_{i+1}\equiv0\pmod K\) 的数分为一段来计算。
那么对于一般情况,它们必须满足相邻两数余数分别为 \(r_i\) 和 \(K-r_i\) 才可交换,否则不可以。所以对于同一个余数 \(r_i\),它们对应的数的相对位置是不会改变的。设余数为 \(r_i\) 的数有 \(x\) 个,余数为 \(K-r_i\) 的数有 \(y\) 个,那么这就相当于往一个长为 \(x+y\) 的序列中选择 \(x\) 个放 \(r_i\),剩下的放 \(K-r_i\),则这一段的贡献是
\[\binom{x+y}{x}
\]
但是我们发现有两类数比较特殊,它们对应的 \(r_i\) 等于 \(0\) 或 \(K/2\)(如果 \(K\) 是偶数)。此时它们在同一段内任意交换顺序也能够满足条件。设这一段长度为 \(len\),这一段中值 \(v\) 出现了 \(cnt_v\) 次,那么这一段的贡献就是多重集全排列数
\[\frac{len!}{\prod_v cnt_v!}
\]
最终答案就是每一段的方案数相乘。
时间复杂度 \(O(T\sum n)\)。
Code
int n, k;
int a[N];
mo fac[N], inv[N];//mo 是手写的自动取模类
inline void init () {
fac[0] = 1;
for (int i = 1; i <= N - 15; ++ i) fac[i] = fac[i - 1] * i;
inv[N - 15] = ~fac[N - 15];//~ 是求逆元
for (int i = N - 15; i >= 1; -- i) inv[i - 1] = inv[i] * i;
}
inline int get (int x) {
int r = (x % k + k) % k;
if (r == 0) return 0;
if (k % 2 == 0 && r == k >> 1) return k >> 1;
return min (r, k - r);
}//给每个数编号来分段
inline mo C (int n, int m) {
if (n < m || m < 0) return 0;
return fac[n] * inv[m] * inv[n - m];
}
inline void solve () {
cin >> n >> k;
for (int i = 1; i <= n; ++ i) cin >> a[i];
mo ans = 1;
for (int i = 1; i <= n; ) {
int j = i;
int id = get (a[i] % k);
while (j <= n && get (a[j] % k) == id) ++ j;
int len = j - i;
if (!id || (k % 2 == 0 && id == k >> 1)) {
unordered_map <i64, int> mp;
for (int l = i; l < j; ++ l) ++ mp[a[l]];
mo x = fac[len];
for (auto p : mp) x *= inv[p.second];
ans *= x;
}//余数为 0 或 K/2
else {
int cnt1 = 0, cnt2 = 0;
for (int l = i; l < j; ++ l) {
int r = (a[l] % k + k) % k;
if (r == id) ++ cnt1;
else cnt2 ++;
}
if (cnt1 && cnt2) ans *= C (cnt1 + cnt2, cnt1);
}//一般情况
i = j;
}
cout << ans << endl;
}

浙公网安备 33010602011771号