Seat
Posted Tan_tan_tann
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Seat相关的知识,希望对你有一定的参考价值。
Seat
题解
我们可以先将男性位置的顺序去掉,单看成
1
,
2
,
3
,
4
,
.
.
.
,
n
1,2,3,4,...,n
1,2,3,4,...,n的序列,先考虑女性的位置该怎么插,最后再加入男性的顺序。
很明显,对于
i
i
i与
i
+
1
i+1
i+1位置之间的女性,她既不能为
i
i
i也不能为
i
+
1
i+1
i+1。女性也看成一个序列
P
P
P,那么
P
i
≠
i
∧
P
i
≠
i
+
1
P_{i}\\not =i\\wedge P_{i}\\not =i+1
Pi=i∧Pi=i+1。
这不是Three Permutations吗,要让找一个排列与其它两个排列都不同,转化成图就是一个在大小为
n
n
n的环。
所以我们只要
D
P
DP
DP后加个容斥就可以得到
70
p
t
s
70pts
70pts了。
这个做法同样给了我们一个提示,我们可以用容斥的方法求出答案。
我们考虑有
x
x
x个位置不合法的情况可以怎么计算。
我们可以先枚举不合法的位置,除了这些不合法的位置,其它的男女都是随便放的,也就是
(
(
n
−
x
)
!
)
2
((n-x)!)^2
((n−x)!)2。
而这些不合法的位置肯定有相对的顺序,乘上
x
!
x!
x!。
最后还要将这些不合法的位置放回排列中,我们相当于在
2
n
−
x
2n-x
2n−x个元素中任选
x
x
x个,让这
x
x
x个延伸一位,表示一个不合法对占据的两位,有
(
2
n
−
x
x
)
\\binom{2n-x}{x}
(x2n−x)。
所以有
x
x
x个位置不合法的情况就有
(
(
n
−
x
)
!
)
2
x
!
(
2
n
−
x
x
)
((n-x)!)^2x!\\binom{2n-x}{x}
((n−x)!)2x!(x2n−x)种,可以用容斥得到最后的答案,
A
n
s
=
∑
i
=
0
n
(
−
1
)
i
(
(
n
−
i
)
!
)
2
i
!
(
2
n
−
i
i
)
Ans=\\sum_{i=0}^{n}(-1)^i((n-i)!)^2i!\\binom{2n-i}{i}
Ans=i=0∑n(−1)i((n−i)!)2i!(i2n−i)
时间复杂度 O ( n ) O\\left(n\\right) O(n)。
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define MAXN 200005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL;
const LL INF=1000000000000000000LL;
const int mo=998244353;
const int inv2=499122177;
const int jzm=2333;
const int lim=100000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-7;
typedef pair<int,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,fac[MAXN],inv[MAXN],f[MAXN],ans;
void init(){
fac[0]=fac[1]=inv[0]=inv[1]=f[1]=1;
for(int i=2;i<=n+n;i++)
fac[i]=1ll*i*fac[i-1]%mo,
f[i]=1ll*(mo-mo/i)*f[mo%i]%mo,
inv[i]=1ll*f[i]*inv[i-1]%mo;
}
int C(int x,int y){
if(x<0||y<0||x<y)return 0;
return 1ll*fac[x]*inv[y]%mo*inv[x-y]%mo;
}
signed main(){
read(n);init();
for(int i=0;i<=n;i++){
int tmp=1ll*fac[n-i]*fac[n-i]%mo*fac[i]%mo*add(C(n+n-i,i),C(n+n-i-1,i-1),mo)%mo*C(n,i)%mo;
if(i&1)ans=add(ans,mo-tmp,mo);else ans=add(ans,tmp,mo);
}
printf("%d\\n",1ll*ans*f[n]%mo);
return 0;
}
谢谢!!!
以上是关于Seat的主要内容,如果未能解决你的问题,请参考以下文章