BZOJ2982

2982: combination

Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 628 Solved: 379

Description

LMZ有n个不同的基友,他每天晚上要选m个进行[河蟹],而且要求每天晚上的选择都不一样。那么LMZ能够持续多少个这样的夜晚呢?当然,LMZ的一年有10007天,所以他想知道答案mod 10007的值。(1<=m<=n<=200,000,000)

Input

第一行一个整数t,表示有t组数据。(t<=200)

接下来t行每行两个整数n, m,如题意。

Output

T行,每行一个数,为C(n, m) mod 10007的答案。

Sample Input

4
5 1
5 2
7 3
4 2

Sample Output

5
10
35
6

解题思路:

这道题其实就是求组合数取模,一套Lucas定理打上去完事。

代码如下:

#include <iostream>
#include <cstdio>
#define  LL long long
using namespace std;

const int p = 10007;

LL fpow(int a,int b){
    LL res = 1;
    while(b){
        if(b&1)res = (res*a)%p;
        a = (a*a)%p;
        b >>= 1;
    }
    return res;
}

LL C(int m,int n){
    LL res1 = 1,res2 = 1;
    for(int i = 1;i <= n; i++)res1 = (res1*i)%p;
    for(int j = m-n+1;j <= m; j++)res2 = (res2*j)%p;
    return (res2*fpow(res1,p-2))%p;
}

LL lucas(int m,int n){
    LL res = 1;
    while(m && n){
        LL mm = m%p,nn = n%p;
        if(mm < nn)return 0;
        res = (res*C(mm,nn))%p;
        n /= p;
        m /= p;
    }
    return res;
}

int main(){
    int T,n,m;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&m,&n);
        LL ans = lucas(m,n);
        printf("%lld\n",ans%p);
    }
    return 0;
}
posted @ 2017-08-29 17:35  Frade~  阅读(130)  评论(0编辑  收藏  举报