Problem G. Cyclic HDU - 6432(容斥原理)

Problem G. Cyclic HDU - 6432

 Count the number of cyclic permutations of length n with no continuous subsequence [i, i + 1 mod n].
Output the answer modulo 998244353. 

Input
The first line of the input contains an integer T , denoting the number of test cases.
In each test case, there is a single integer n in one line, denoting the length of cyclic permutations.
1 ≤ T ≤ 20, 1 ≤ n ≤ 100000
Output
For each test case, output one line contains a single integer, denoting the answer modulo 998244353.
Sample Input

3
4
5
6

Sample Output

1
8
36

题意:

给你一个n,1-n个数排列成环要求后一个不能刚好比前一个大一(不能包含有 [i, i + 1] 或 [n, 1] 这样的子串),问你有多少种排列方式。

分析:

环排列,顾名思义,一个排列首尾相连成环,长度为n的环排列个数为(n-1)!,因为一个正常的排列对应n个环排列。可以利用容斥原理:

Problem G. Cyclic HDU - 6432(容斥原理)_第1张图片

code:

#include 
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int N = 1e5+10;
ll t,n,f[N],inv[N];
ll q_pow(ll a,ll b){
    ll ans = 1;
    while(b){
        if(b & 1)
            ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}
void init(){
    f[0] = f[1] = 1;
    for(int i = 2; i < N; i++){
        f[i] = f[i-1] * i % mod;
    }
    inv[N-1] = q_pow(f[N-1],mod-2);
    for(int i = N-2; i >= 0; i--){
        inv[i] = inv[i+1] * (i + 1) % mod;
    }
}
ll C(ll x,ll y){
    return f[x] * inv[y] % mod * inv[x-y] % mod;
}
int main(){
    init();
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        ll ans = 0,sig = 1;
        if(n & 1) ans = -1;
        else ans = 1;
        for(int i = 0; i <= n-1; i++){
            if(sig < 0)
                ans = (ans + C(n,i) * sig * f[n-i-1] % mod + mod) % mod;
            else
                ans = (ans + C(n,i) * sig * f[n-i-1] % mod) % mod;
            sig = -sig;
        }
        printf("%lld\n",(ans+mod)%mod);
    }
    return 0;
}

当然也有很多人直接打表然后把前几项扔到oeis上发现有现成的公式结论:

f[i]=(i1)f[i1]+(i1)f[i2](1)i f [ i ] = ( i − 1 ) ⋅ f [ i − 1 ] + ( i − 1 ) ⋅ f [ i − 2 ] − ( − 1 ) i

你可能感兴趣的:(#,组合数学)