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;
}
posted @ 2018-08-24 18:33  ffgcc  阅读(195)  评论(0编辑  收藏  举报