HDU 6432 Problem G. Cyclic(容斥原理)
解释下题意
问这种长度为 n 且本质不同(本质不同是指环上数字的相对位置不同,如 1234 和 2341,3412,4123 都是本质相同的,它们本质上是一个环)的环有多少种。所以打表时可以控制1就在1位置,这样就不会有重复的计数了,然后OEIS一下就能找到这个公式
a(n) = (-1)^n + sum((-1)^k*binomial(n, k)*(n-k-1)!, k=0..n-1)
题解:
考虑使用容斥原理进行计数.
包含至少一个形如 [i, i + 1] 或 [n, 1] 这样的子串的环排列个数是 C(n,1)(n − 2)! 个;
可以推广为包含至少 k(0 ≤ k < n) 个的环排列个数是 C(n,k)(n − k − 1)!,
同时注意到,包含 n 个的环排列个数一定是 1 个.
所以最终答案就是
(−1)^n +∑(k=0,k=n−1)(−1)^k*C(n,k)(n − k − 1)!
#include <bits/stdc++.h>
typedef long long LL;
const int MAXN = 1e5 + 5;
const int MOD = 998244353;
int N;
int fac[MAXN], ifac[MAXN];
int fpm(int base, int exp)
{
int ret = 1;
for (; exp; exp >>= 1) {
if (exp & 1)
ret = (LL)ret * base % MOD;
base = (LL)base * base % MOD;
}
return ret;
}
void prework()
{
fac[0] = ifac[0] = 1;
for (int i = 1; i < MAXN; ++i) {
fac[i] = (LL)fac[i - 1] * i % MOD;
ifac[i] = fpm(fac[i], MOD - 2);
}
}
void solve()
{
int ans = N & 1 ? MOD - 1 : 1;
for (int k = 0; k < N; ++k) {
int t = (LL)fac[N] * ifac[k] % MOD * ifac[N - k] % MOD * fac[N - k - 1] % MOD;
if (k & 1)
(ans += MOD - t) %= MOD;
else
(ans += t) %= MOD;
}
printf("%d\n", ans);
}
int main()
{
prework();
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &N);
solve();
}
return 0;
}