题目链接
https://codeforces.com/contest/1957/problem/C
思路其实不难,最重要的就是一个问题,从n个数中两两配对,有多少种配法
首先进行全排列,即N!除去左右相等的即2的n/2次方,再除去彼此之间没顺序(N/2)!
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<unordered_map>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<cmath>
#include<set>
using namespace std;
#define int long long
typedef long long ll;
const int N=1e6+10;
const int mod=1e9+7;
int n;
int a[N];
int b[N];
int pre[N];
int fpre[N];
int qsm(int a,int b)
{
int ans=1;
int c=a;
while(b!=0)
{
if(b%2==1)
{
ans=ans*c;
ans%=mod;
}
c=c*c;
c%=mod;
b>>=1;
}
return ans%mod;
}
void init()
{ pre[0]=1;
pre[1]=1;
fpre[0]=1;
for(int i=1;i<=310000;i++)
{
pre[i]=pre[i-1]*i;
pre[i]%=mod;
fpre[i]=qsm(pre[i],mod-2);
fpre[i]%=mod;
}
}
int C(int n,int m)
{
return pre[n]*fpre[m]%mod*fpre[n-m]%mod;
}
void solve()
{
int n,k;
cin>>n>>k;
set<int>s;
for(int i=1;i<=k;i++)
{
int x,y;
cin>>x>>y;
s.insert(x);
s.insert(y);
}
n=n-s.size();
if(n==1){
cout<<1<<endl;
return;
}
if(n==2){
cout<<3<<endl;
return;
}
int ans=0;
if(n%2==0)
{
for(int i=0;i<=n;i+=2)
{
ans+=C(n,i)*pre[n-i]%mod*fpre[(n-i)/2]%mod;
ans%=mod;
}
cout<<(ans)%mod<<endl;
}
else{
for(int i=1;i<=n;i+=2)
{
ans+=C(n,i)*pre[n-i]%mod*fpre[(n-i)/2]%mod;
ans%=mod;
}
cout<<(ans)%mod<<endl;
}
}
signed main()
{
int t;
cin>>t;
init();
while(t--)
{
solve();
}
return 0;
}
标签:pre,Rook,int,long,How,Does,ans,include,mod
From: https://www.cnblogs.com/yuhaomice/p/18193800