[BZOJ2982]combination
2982: combination
Time Limit: 1 Sec Memory Limit: 128 MB Submit: 703 Solved: 416 [Submit][Status][Discuss]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
5 1
5 2
7 3
4 2
Sample Output
5
10
35
6
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; }