HDU 6114 Chess【逆元+組合數】(組合數模板題)
阿新 • • 發佈:2018-08-13
模板題 tro 正整數 現在 ros 沒有 algo clas tdi
現在要問問你,滿足要求的方案數是多少。
<題目鏈接>
題目大意:
車是中國象棋中的一種棋子,它能攻擊同一行或同一列中沒有其他棋子阻隔的棋子。一天,小度在棋盤上擺起了許多車……他想知道,在一共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
1
解題分析:
其實仔細推敲這題之後,不難發現,由於n和m不一定想等,所以在棋盤中放置最多個數的車,並使其不攻擊,即求 C(max(n,m),min(n,m))。因為,假設n>m,即行數大於列數,此時要使棋盤中車盡可能的多,只能每一列都放一個車,而這m個車擺放的不同方案數即為在 n行中挑選出 m行來放這 m個車。所以,此題就很自然的轉化為了組合數的求解。
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #define ll long long using namespace std; const int mod = 1000000007; ll fast_pow(ll x, ll n) { ll ans = 1; while (n) { if (n & 1) ans = (ans*x) % mod; x = (x*x) % mod; n >>= 1; } return ans; } ll inv(ll a, ll p)//費馬定理求a關於p的逆元 { return fast_pow(a, p - 2); } ll C(ll n, ll m) //求n中挑選m個的方案數 { ll ans = 1; for (ll i = n - m + 1; i <= n; i++) ans = (ans*i) % mod; for (ll i = 1; i <= m; i++) ans = (ans*inv(i, mod)) % mod; return ans; } int main() { int t; scanf("%d", &t); while (t--) { ll n, m; scanf("%lld%lld", &n, &m); printf("%lld\n", C(max(n, m), min(n, m))); } return 0; }
2018-08-12
HDU 6114 Chess【逆元+組合數】(組合數模板題)