Problem G. Cyclic
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 322 Accepted Submission(s): 225
Problem Description
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
题意:
给你一个t
然后t组数据,每组数据一个n,让你给出长度为n的循环排列满足条件的方案数%998244353
条件,队列中前一个数+1≠后一个数,并且n后面不能放1
例如n=4,只有1 4 3 2满足
解析:
官方题解:
考虑使用容斥原理进行计数.
包含至少一个形如 或 这样的子串的环排列个数是 个;
可以推广为包含至少 个的环排列个数是 ,
同时注意到包含 n个的环排列个数一定是 1 个.
所以最终答案就是
这里长度为n的循环排列的方案数是(n-1)!
所以当k=4时,就是,然后再把取出来的数合并之后放回去,组成n-k个数求方案数(n-k-1)!
例如取[2,3,4,5,6] n-5+1=n-4
取[2,3,4],[6,7,8] n-6+2=n-4
取[2,3],[5,6],[8,9],[11,12] n-8+4=n-4
然后就是上面的容斥了,
最后那个包含n个的时候我具体搞不懂为什么,下面是我根据容斥猜的。
最后k=n时,因为(n-k-1)<0,但是k=n时确实是存在一种方案的,所以还要继续容斥,容斥系数就是(-1)^n
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
const int MAXN = 1e5+10;
const ll MOD = 998244353;
ll jc[MAXN];
ll inv[MAXN];
void init()
{
ll p=1;
jc[0]=1;
jc[1]=1;
inv[0]=1;
inv[1]=1;
for(int i=2;i<MAXN;i++)
{
p=(p*i)%MOD;
jc[i]=p;
//inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD;
}
for(int i=2;i<MAXN;i++) inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD; //O(n)求逆元
for(int i=2;i<MAXN;i++) inv[i]=inv[i-1]*inv[i]%MOD; //扩展到i!的逆元
}
inline ll C(int a, int b) //计算C(a, b),a下,b上
{
if(b>a) return 0;
return jc[a] * inv[b] % MOD
* inv[a-b]%MOD;
}
int main()
{
int t;
cin>>t;
init();
while(t--)
{
int n;
cin>>n;
ll ans=0;
for(int i=0;i<n;i++)
{
ans=(i&1)?(ans-(C(n,i)*jc[n-i-1]%MOD)+MOD)%MOD:(ans+(C(n,i)*jc[n-i-1]%MOD))%MOD;
}
if((n&1)==0) ans++;
else ans--;
ans=(ans+MOD)%MOD;
printf("%lld\n",ans);
}
return 0;
}