CF1516E. Baby Ehab Plays with Permutations
Solution
因为组合水平不行所以只弄出来一个
O
(
k
4
)
O(k^4)
O(k4)的做法(虽然随便改改可能就
O
(
k
3
log
k
)
O(k^3\log k)
O(k3logk)或者
O
(
k
3
)
O(k^3)
O(k3)了)而且因为没想清楚而自闭了很久,从而导致摸yu时间被阉割。
首先大概有个显然的性质:设一个任意的操作方案形成的最终序列为 a 1 , a 2 . . . a n a_1,a_2...a_n a1,a2...an,把 i i i和 a i a_i ai连边,会形成若干个环,有个显然的结论是到达该状态的最少操作次数是所有环长度减一的和,而一个任意方案可以表示为最少操作方案加上若干无用操作,显然无用操作个数为偶数(由逆序对个数奇偶性可得),因此我们只需要计算最少 i i i步能到达的状态个数 A n s i Ans_i Ansi,再让 A n s i ′ = ∑ k = 0 ⌊ i 2 ⌋ A n s i − 2 k Ans'_i=\sum_{k=0}^{\lfloor\frac{i}{2}\rfloor}Ans_{i-2k} Ansi′=∑k=0⌊2i⌋Ansi−2k即为最终的答案。
因此我们要对每一个 i i i,求出最少 i i i步能到达的状态个数。
这就相当于取若干个环,使得所有环的长度减一的和为
i
i
i,也就类似于做一个完全背包,取
j
j
j个数形成环的方案数就是环排列个数
(
j
−
1
)
!
(j-1)!
(j−1)!,因此枚举枚举环长
i
i
i,枚举该种环的个数
p
p
p,再枚举环包含的点数
j
j
j和操作次数
k
k
k,可得:
f
j
,
k
=
∑
p
f
j
−
i
p
,
k
−
(
i
−
1
)
p
(
i
−
1
)
p
(
j
i
p
)
∏
t
=
0
p
−
1
(
i
p
−
i
t
−
1
i
−
1
)
f_{j,k}=\sum_{p}f_{j-ip,k-(i-1)p} (i-1)^p\binom{j}{ip}\prod_{t=0}^{p-1}\binom{ip-it-1}{i-1}
fj,k=p∑fj−ip,k−(i−1)p(i−1)p(ipj)t=0∏p−1(i−1ip−it−1)
A n s i = ∑ j f j , i ( n j ) Ans_{i} = \sum_{j} f_{j,i}\binom{n}{j} Ansi=j∑fj,i(jn)
预处理一些东西即可计算。
Code
int fac[405], Inv[405], C[405][405], f[405][205], Ans[405], tmp[405][205], inv[405], Mul[405];
int quick_pow(int x, int y) {
int ret = 1;
for (; y ; y >>= 1) {
if (y & 1) ret = 1ll * ret * x % mods;
x = 1ll * x * x % mods;
}
return ret;
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("a.in", "r", stdin);
#endif
int n, k;
read(n), read(k);
fac[0] = inv[0] = Inv[0] = 1;
for (int i = 1; i <= k + k ; ++ i) Inv[i] = quick_pow(i, mods - 2);
for (int i = 1; i <= k + k ; ++ i) fac[i] = 1ll * fac[i - 1] * i % mods, inv[i] = quick_pow(fac[i], mods - 2);
for (int i = 0; i <= k + k ; ++ i) C[i][i] = C[i][0] = 1;
for (int i = 1; i <= k + k ; ++ i)
for (int j = 1; j < i ; ++ j) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mods;
f[0][0] = 1;
for (int i = 2; i <= min(n, k + 1) ; ++ i) {
for (int j = 0; j <= k + k ; ++ j)
for (int t = 0; t <= k ; ++ t) tmp[j][t] = f[j][t], f[j][t] = 0;
for (int j = 0; j <= k + k ; ++ j) Mul[j] = 1;
for (int p = 0, mul = 1; p <= k ; ++ p) {
for (int j = i * p ; j <= k + k ; ++ j) {
for (int t = (i - 1) * p ; t <= k ; ++ t)
f[j][t] = (f[j][t] + 1ll * tmp[j - i * p][t - (i - 1) * p] * Mul[i * p] % mods * mul % mods * C[j][i * p] % mods) % mods;
}
for (int j = k + k; j >= 0 ; -- j)
if (j >= i) Mul[j] = 1ll * Mul[j - i] * C[j - 1][i - 1] % mods;
else Mul[j] = 0;
mul = 1ll * mul * fac[i - 1] % mods;
}
}
for (int i = 0, mul = 1; i <= min(k + k, n) ; ++ i) {
for (int j = 0; j <= k ; ++ j)
Ans[j] = (Ans[j] + 1ll * f[i][j] * mul % mods * inv[i] % mods) % mods;
mul = 1ll * mul * (n - i) % mods;
}
for (int i = 2; i <= k ; ++ i) Ans[i] = (Ans[i] + Ans[i - 2]) % mods;
for (int i = 1; i <= k ; ++ i) print(Ans[i]), putc(' ');
return 0;
}