[计蒜客] 受力平衡(组合数学 + 乘法逆元)

摘要:从n个a物品和m个b物品各选取i个的方案数

解法:问题可以看成从n+m个物品中选取i个b物品和m-i个a物品

那么原问题可推出公式:$C(n,1)^2+C(n,2)^2+...+C(n,n)^2=C(2n,n)$

 [相关证明](http://discrete.openmathbooks.org/dmoi2/sec_comb-proofs.html)

预处理阶乘,求解组合数的时候由于有除法,于是要套一个求逆元

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=2e6+10;
const ll MOD=1e9+7;
ll f[MAXN],n,m;
ll fp(ll a,ll b){
    ll ret=1;
    while(b){
        if(b&1)    ret=ret*a%MOD;    
        a=a*a%MOD;
        b>>=1;
    }
    return ret;
}
ll C(ll n,ll m){
    ll fm=f[m]*f[n-m]%MOD,fz=f[n];
    return fz*fp(fm,MOD-2)%MOD;
}

int main(){
    f[0]=1;
    for(int i=1;i<=MAXN-5;++i)    f[i]=f[i-1]*i%MOD;
    int t;
    cin>>t;
    while(t--){
        scanf("%lld%lld",&n,&m);
        printf("%lld\n",(C(n+m,m)-1+MOD)%MOD);
    }
    return 0;
}
View Code

 

posted @ 2020-03-07 18:50  JNzH  阅读(234)  评论(0编辑  收藏  举报