hdu3037(lucas定理)

给定n,m,p   表示<=m个豆子放在n棵树上,一共有多少种方案数,  总的方案书mod p

如果将m个豆子放在n棵树上, 可以使用插板法

得到方案数是C(n+m-1,n-1)

那么将0<=i<=m个豆子放在n棵上的方案数是  C(n+i-1,n-1)

其中C(n,k)=C(n-1,k)+C(n-1,k-1) 的意思是从n个数中取出k个的组合,  那么对于一个数来说,它要么不取,转为C(n-1,k), 要么取转为C(n-1,k-1)

 

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <stdlib.h>
 4 #include <algorithm>
 5 #include <iostream>
 6 #include <queue>
 7 #include <stack>
 8 #include <vector>
 9 #include <map>
10 #include <set>
11 #include <string>
12 #include <math.h>
13 using namespace std;
14 #pragma warning(disable:4996)
15 typedef long long LL;                   
16 const int INF = 1<<30;
17 /*
18 
19 */
20 
21 LL fact[100001];
22 
23 LL pow(LL a, LL k, LL p)
24 {
25     LL ret = 1;
26     while (k)
27     {
28         if (k & 1)
29             ret = ret * a %p;
30         a = a * a % p;
31         k >>= 1;
32     }
33     return ret;
34 }
35 LL C(LL n, LL m, LL p)
36 {
37     if (n < m || m < 0) return 0;
38     LL a = fact[n], b = fact[n - m] * fact[m] % p;
39     return a * pow(b, p - 2, p) % p;
40 }
41 LL lucas(int n, int m, int p)
42 {
43     if (m == 0) return 1;
44     return C(n%p, m%p,p) * lucas(n / p, m / p, p) % p;
45 }
46 int main()
47 {
48     int t, n, m, p;
49     scanf("%d", &t);
50     while (t--)
51     {
52         scanf("%d%d%d", &n, &m, &p);
53         fact[0] = 1;
54         for (int i = 1; i <= p; ++i)
55             fact[i] = fact[i - 1] * i % p;
56         printf("%I64d\n", lucas(n + m, n, p));
57 
58     }
59     return 0;
60 }

 

posted @ 2015-06-25 19:40  justPassBy  阅读(271)  评论(0编辑  收藏  举报