解法
用容斥原理做
假設P(n,i)
表示n
對夫婦時,有i
隊夫婦粘在一起的種類數:
我們選出i
對夫婦,有C(m,i)
種可能,把粘在一起的夫婦算做一個人,總共有2n-i
個人全排列種排法,每個粘在一起的夫婦都有2種排法,所以總共有種可能,整個問題的種類數就爲:
用時間算出這三部分的值,存起來,其中第一部分要變成,第三部分要變成
然後再用時間求和就行了
python會超時,改成c++就好了= =
#include <stdio.h>
#include <string>
#include <iostream>
#include <memory.h>
#include <stdlib.h>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <functional>
#define MAXN 100010
#define NINF -100000
#define INF 65536
using namespace std;
typedef long long lld;
int n,m;
const int MOD = 1000000007;
const int minus2 = MOD-2;
int A[MAXN],C[MAXN],B[MAXN<<1];
int maxn,maxm;
int POW(int i,int k) {
int res = 1;
int base = i;
while (k>0) {
if (k&1)
res = (lld)res*base%MOD;
base = (lld)base*base%MOD;
k = k>>1;
}
return res;
}
int solve() {
for(int i=maxm+1;i<=m;++i) {
A[i] = (lld)A[i-1]*minus2%MOD;
}
for(int i=1;i<=m;++i) {
C[i] = (lld)(m-i+1)*POW(i,minus2)%MOD*C[i-1]%MOD;
}
maxm = max(m,maxm);
int UP = (n<<1);
for(int i=(maxn<<1)+1;i<=UP;++i) {
B[i] = (lld)B[i-1]*i%MOD;
}
maxn = max(n,maxn);
int ans = B[n<<1];
for(int i=1;i<=m;++i) {
ans = (ans+(lld)A[i]*B[2*n-i]%MOD*C[i]%MOD)%MOD;
}
return ans;
}
int main() {
// freopen("/Users/huangyuemei/CLionProjects/untitled/C-large-practice.in","r",stdin);
// freopen("/Users/huangyuemei/CLionProjects/untitled/my.out","w",stdout);
A[0] = C[0] = B[0] = 1;
maxn = maxm = 0;
int t;
scanf("%d",&t);
for(auto round=1;round<=t;++round) {
scanf("%d%d",&n,&m);
printf("Case #%d: %d\n",round,solve());
}
}