原文地址:http://www.cnblogs.com/GXZlegend/p/6801490.html
题目描述
LMZ有n个不同的基友,他每天晚上要选m个进行[河蟹],而且要求每天晚上的选择都不一样。那么LMZ能够持续多少个这样的夜晚呢?当然,LMZ的一年有10007天,所以他想知道答案mod 10007的值。(1<=m<=n<=200,000,000)
输入
第一行一个整数t,表示有t组数据。(t<=200)
接下来t行每行两个整数n, m,如题意。
输出
T行,每行一个数,为C(n, m) mod 10007的答案。
样例输入
4
5 1
5 2
7 3
4 2
样例输出
5
10
35
6
题解
Lucas定理:C(n , m) mod p = C(n/p , m/p) * C(n mod p , m mod p) mod p(p为质数)
然后快速幂求个逆元就没啥了。
#include <cstdio>
#define mod 10007
int fac[10010];
int pow(int x , int y)
{
int ans = 1;
while(y)
{
if(y & 1) ans = ans * x % mod;
x = x * x % mod , y >>= 1;
}
return ans;
}
int cal(int n , int m)
{
if(n < m) return 0;
return fac[n] * pow(fac[m] , mod - 2) % mod * pow(fac[n - m] , mod - 2) % mod;
}
int lucas(int n , int m)
{
if(!m) return 1;
return cal(n % mod , m % mod) * lucas(n / mod , m / mod) % mod;
}
int main()
{
int t , n , m , i;
scanf("%d" , &t);
fac[0] = 1;
for(i = 1 ; i < mod ; i ++ ) fac[i] = fac[i - 1] * i % mod;
while(t -- )
{
scanf("%d%d" , &n , &m);
printf("%d\n" , lucas(n , m));
}
return 0;
}