bzoj2982: combination(Lucas定理)
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
$n,m$这么大,$mod$这么小
上个裸的$Lucas$
解决。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define re register 5 using namespace std; 6 int min(int a,int b){return a<b?a:b;} 7 const int p=1e4+7; 8 int t,n,m,fac[p+2]; 9 int Pow(int x,int y){ 10 int res=1; 11 for(;y;y>>=1,x=1ll*x*x%p) 12 if(y&1) res=1ll*res*x%p; 13 return res; 14 } 15 int C(int a,int b){ 16 return a<b?0:1ll*fac[a]*Pow(fac[b],p-2)%p*Pow(fac[a-b],p-2)%p; 17 } 18 int lucas(int a,int b){ 19 return b?1ll*lucas(a/p,b/p)%p*C(a%p,b%p)%p:1; 20 } 21 int main(){ 22 scanf("%d",&t); fac[0]=1; 23 for(int i=1;i<=p;++i) fac[i]=1ll*fac[i-1]*i%p; 24 while(t--){ 25 scanf("%d%d",&n,&m); 26 printf("%d\n",lucas(n,min(m,n-m))); 27 }return 0; 28 }