【Kickstart】2018 Round H - Let Me Count The Ways

解法

用容斥原理做
假設P(n,i)表示n對夫婦時,有i隊夫婦粘在一起的種類數:
我們選出i對夫婦,有C(m,i)種可能,把粘在一起的夫婦算做一個人,總共有2n-i個人全排列種排法,每個粘在一起的夫婦都有2種排法,所以總共有P(n,i)=2i(2ni)!CmiP(n,i) = 2^i(2n-i)!C_m^i種可能,整個問題的種類數就爲:
S(n,m)=P(n,0)P(n,1)+P(n,2)....=i=0m(1)iP(n,i)=i=0m(2)i(2ni)!CmiS(n,m) = P(n,0)-P(n,1)+P(n,2)....\\=\sum_{i=0}^m(-1)^iP(n,i)\\=\sum_{i=0}^m(-2)^i(2n-i)!C_m^i
O(m+n)O(m+n)時間算出這三部分的值,存起來,其中第一部分要變成(MOD2)i(MOD-2)^i,第三部分要變成Cmi=(mi+1)iMOD2Cmi1C_m^i = (m-i+1)i^{MOD-2}C_m^{i-1}
然後再用O(m)O(m)時間求和就行了
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());
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章