天天看點

Chess(組合數,逆元)

連結: http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=776&pid=1001

Chess Accepts: 1805 Submissions: 5738

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Problem Description

車是中國象棋中的一種棋子,它能攻擊同一行或同一列中沒有其他棋子阻隔的棋子。一天,小度在棋盤上擺起了許多車……他想知道,在一共N×M個點的矩形棋盤中擺最多個數的車使其互不攻擊的方案數。他經過思考,得出了答案。但他仍不滿足,想增加一個條件:對于任何一個車A,如果有其他一個車B在它的上方(車B行号小于車A),那麼車A必須在車B的右邊(車A列号大于車B)。

現在要問問你,滿足要求的方案數是多少。

Input

第一行一個正整數T,表示資料組數。

對于每組資料:一行,兩個正整數N和M(N<=1000,M<=1000)。

Output

對于每組資料輸出一行,代表方案數模1000000007(1e9+7)。

Sample Input

1

1 1

Sample Output

Copy

1

分析:組合數 C(n,m)

一直TLE,沒想到與逆元結合,其實還是挺簡單的。。。還是渣  由組合數的公式,還要取模,大數除法取模,就是逆元了

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int mod=+;
const int N=+;
typedef long long LL;
LL fac[N],inv[N];
LL pow_mod(LL a,LL b)
{
    LL ans=;
    a%=mod;
    while(b)
    {
        if(b&) ans=ans*a%mod;
        b>>=;
        a=a*a%mod;
    }
    return ans;
}
void init()
{
    inv[]=fac[]=;
    for(int i=;i<N;i++)
    {
        fac[i]=fac[i-]*i%mod;
        inv[i]=pow_mod(fac[i],mod-);///inv數組為對應的逆元
    }
}
int main()
{
    int t;
    init();
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        if(n<m) swap(n,m);///n始終為大的那個
         //printf("fac[%d]=%d  fac[%d]=%d\n",n,fac[n],m,fac[m]);
        printf("%I64d\n",fac[n]*inv[m]%mod*inv[n-m]%mod);
    }
    return ;
}