Saving Beans 组合数学之 Lucas定理

                   Saving Beans

题目抽象:有n颗水果树,每科树上有无穷多个水果(同一棵树上的水果相同)。现在要从这n棵树上取不超过m个水果,有多少种取法。

ps:S={n1*a1,n2*a2,n3*a3,……,nn*an}.若m<ni(i=1,2,...n)   则s的m组合=T={m*1,(n-1)*0} =  (m+n-1)!/(m!)/(n!)=c(m+n-1,m);

思路:利用一一对应的思想,再增加一棵树。从n+1棵树上取m个水果的方案数。

ans=T={m*1,n*0}=(m+n)!/m!/n!=c(n+m,m);

Lucas定理是用来求 c(n,m) mod p,p是素数的值。

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 using namespace std;
 7 typedef long long LL;
 8 
 9 void ex_gcd(LL a,LL b,LL &d,LL &x,LL &y)
10 {
11     if(b==0)
12     {
13         x=1;y=0;d=a;
14     }
15     else
16     {
17         ex_gcd(b,a%b,d,y,x);
18         y-=(a/b)*x;
19     }
20 }
21 
22 LL inv(LL a,LL m)
23 {
24     LL d,x,y;
25     ex_gcd(a,m,d,x,y);
26     if(d==1)
27         return (x%m+m)%m;    //x可能为负数
28     return -1;
29 }
30 
31 LL CM(LL n,LL m,LL p)
32 {
33     LL a=1,b=1;
34     if(m>n)
35         return 0;
36     //c(n,m)=c(n,m-1)*(n-m+1)/m;  O(m) 求c(n,m)
37     while(m)
38     {
39         a=(a*n)%p;
40         b=(b*m)%p;
41         m--;
42         n--;
43     }
44     return (a*inv(b,p))%p;
45 }
46 
47 //   Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p)
48 LL Lucas(LL n,LL m,LL p)
49 {
50     if(m==0)
51         return 1;
52     return (CM(n%p,m%p,p)*Lucas(n/p,m/p,p))%p;
53 }
54 
55 int main()
56 {
57     int T;
58     scanf("%d",&T);
59     while(T--)
60     {
61         LL n,m,p;
62         scanf("%lld%lld%lld",&n,&m,&p);
63         printf("%lld\n",Lucas(n+m,m,p));
64     }
65     return 0;
66 }

 

转载于:https://www.cnblogs.com/hutaishi/p/4489477.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值