[BZOJ2982]combination

2982: combination

Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 703  Solved: 416 [Submit][Status][Discuss]

Description

LMZn个不同的基友,他每天晚上要选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定理
$C_n^m=C_{n\% p}^{m\% p}*C_{n/p}^{m/p}\% p$
#include <cstdio>
const int mod = 10007;
int ksm(int a, int b){
    int s = 1;
    while(b){
        if(b & 1) s = s * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return s;
}
int fac[mod + 10], inv[mod + 10];
inline int C(int n, int m){
    if(n < m) return 0;
    return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
int Lucas(int n, int m){
    if(!m) return 1;
    return C(n % mod, m % mod) * Lucas(n / mod, m / mod) % mod;
}
int main(){
    fac[0] = 1;
    for(int i = 1; i < mod; i++) fac[i] = fac[i - 1] * i % mod;
    inv[mod - 1] = ksm(fac[mod - 1], mod - 2);
    for(int i = mod - 2; ~i; i--) inv[i] = inv[i + 1] * (i + 1) % mod;
    int t, n, m;
    scanf("%d", &t);
    while(t--){
        scanf("%d %d", &n, &m);
        printf("%d\n", Lucas(n, m));
    }
    return 0;
}

 

posted @ 2017-11-03 21:16  jzyy  阅读(107)  评论(0编辑  收藏  举报