lucas定理 FOJ 2020 组合

 Problem 2020 组合

Accept: 886    Submit: 2084
Time Limit: 1000 mSec    Memory Limit : 32768 KB

Problem Description

给出组合数C(n,m), 表示从n个元素中选出m个元素的方案数。例如C(5,2) = 10, C(4,2) = 6.可是当n,m比较大的时候,C(n,m)很大!于是xiaobo希望你输出 C(n,m) mod p的值!

Input

输入数据第一行是一个正整数T,表示数据组数 (T <= 100) 接下来是T组数据,每组数据有3个正整数 n, m, p (1 <= m <= n <= 10^9, m <= 10^4, m < p < 10^9, p是素数)

Output

对于每组数据,输出一个正整数,表示C(n,m) mod p的结果。

Sample Input

2 5 2 3 5 2 61

 Sample Output

1 10 
未预处理阶乘(在组合数函数中写了个循环):
 1 #include<iostream>
 2 using namespace std;
 3 #include<cstdio>
 4 #define ll long long
 5 int t;
 6 ll quick_mod(ll a,ll b,ll p)// a^b%p
 7 {
 8     a%=p;
 9     ll ans=1;
10     while(b)
11     {
12         if(b&1)
13         {
14             b--;
15             ans=(ans*a)%p;
16         }
17         b>>=1;
18         a=(a*a)%p;
19     }
20     return ans;
21 }
22 ll C(ll n, ll m,ll p)
23 {
24     if(m>n) return 0;
25     ll ans=1,a,b;
26     for(int i=1;i<=m;++i)
27     {
28         a=(n+i-m)%p;
29         b=i%p;
30         ans=ans*(a*quick_mod(b,p-2,p)%p)%p;
31     }
32     return ans;
33 }
34 ll lucas(ll n,ll m,ll p)
35 {
36     if(m==0) return 1;
37     return (lucas(n/p,m/p,p)*C(n%p,m%p,p))%p; 
38 }
39 int main()
40 {
41     scanf("%d",&t);
42     while(t--)
43     {
44         ll n,m,p;
45         cin>>n>>m>>p;
46         cout<<lucas(n,m,p)<<endl;
47     }
48     return 0;
49 }

预处理阶乘(有时可以加快速度,相乘时也要防止溢出):

 1 /*事实上,这道题目预处理阶乘,反而会更慢,因为题目中n,m都是10^9,预处理已经接近超时了*/
 2 #include<iostream>
 3 using namespace std;
 4 #include<cstdio>
 5 #define S 10000000
 6 #define ll long long
 7 int t;
 8 long long f[1000000];
 9 void yuchuli(ll p)
10 {
11     f[0]=1;
12     for(int i=1;i<=S;++i)
13       f[i]=f[i-1]*i%p;
14 }
15 ll quick_mod(ll a,ll b,ll p)
16 {
17     a%=p;
18     ll ans=1;
19     while(b)
20     {
21         if(b&1)
22         {
23             b--;
24             ans=(ans*a)%p;
25         }
26         b>>=1;
27         a=(a*a)%p;
28     }
29     return ans;
30 }
31 ll C(ll n, ll m,ll p)
32 {
33     if(m>n) return 0;
34     return (f[n]*quick(f[m]*f[n-m],p-2,p))%p;
35 }
36 ll lucas(ll n,ll m,ll p)
37 {
38     if(m==0) return 1;
39     return (lucas(n/p,m/p,p)*C(n%p,m%p,p))%p; 
40 }
41 int main()
42 {
43     scanf("%d",&t);
44     while(t--)
45     {
46         ll n,m,p;
47         cin>>n>>m>>p;
48         cout<<lucas(n,m,p)<<endl;
49     }
50     return 0;
51 }

 

 
posted @ 2016-05-22 19:45  csgc0131123  阅读(278)  评论(0编辑  收藏  举报