連結: 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 ;
}