题解:P16661 [GKS 2018 #H] Let Me Count The Ways
PigeonTree · · 题解
【题目传送门】
题目思路
令
但是仔细想想就会发现正着去求比较麻烦,所以考虑倒着去求,用总方案数,减去不合法的方案数。
易得
所有不合法的方案就是所有
这时候就可以使用容斥原理了!
但是,如果是真的枚举是否选择每对夫妻的话是一共
再细思,发现我们并不在意每次枚举的夫妻谁是谁,只要加、减去对应的方案数,所以我们只用算出一种可能就行了。综上,我们只用枚举选择的夫妻个数
综合一下,最终我们所求的答案就是:
对于实际实现的时候,我们可以
:::success[AC 代码]{open}
#include<bits/stdc++.h>
#define TESTING 0
#define ift if(TESTING)
#define ft first
#define sd second
#define pb push_back
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define int long long
using namespace std;
const int N=2e5+5,INF=0x3f3f3f3f,MOD=1e9+7;
int cases=1;
int n,m,inv[N],fac[N];
auto qpow=[](int a,int b)->int{
int res=1;
while(b){
if(b&1)res=(res*a)%MOD;
a=(a*a)%MOD;
b>>=1;
}
return res%MOD;
};
auto pre()->void{
fac[0]=1;
inv[0]=1;
for(int i=1;i<=2e5;i++){
fac[i]=fac[i-1]*i%MOD;
inv[i]=qpow(fac[i],MOD-2)%MOD;
}
}
auto A(int n,int m)->int{
return fac[n]*inv[n-m]%MOD;
}
auto C(int n,int m)->int{
return A(n,m)*inv[m]%MOD;
}
auto init()->void{}
auto solution()->void{
cin>>n>>m;
int ans=fac[2*n];
for(int i=1;i<=m;i++){
ans=(ans+(i%2==0?1:MOD-1)*1LL*C(m,i)%MOD*qpow(2,i)%MOD*A(2*n-i,2*n-i)%MOD+MOD)%MOD;
}
cout<<"Case #"<<cases<<": "<<ans<<"\n";
}
auto main()->signed{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int T=1;
cin>>T;
pre();
while(T--){
init();
solution();
cases++;
}
return 0;
}
:::