码迷,mamicode.com
首页 > 其他好文 > 详细

卢卡斯定理

时间:2018-02-23 10:51:37      阅读:266      评论:0      收藏:0      [点我收藏+]

标签:tail   cas   src   证明   技术分享   int   ima   组合   namespace   

参考博客:

http://www.cnblogs.com/owenyu/p/6724560.html

http://blog.csdn.net/raalghul/article/details/51752369

http://www.cnblogs.com/candy99/p/6637629.html 

 

结论:

若p是质数,令n=a*p+b,m=c*p+d,  b,d ∈[0,p)

技术分享图片

 

 

证明:

 

首先证明 在模p意义下

技术分享图片  

 

证明法一:

由费马小定理,技术分享图片 得

技术分享图片

技术分享图片

 

 

证明法二:

当j∈[1,p-1] 时,技术分享图片 (p是质数,j∈[1,p-1],j在模p意义下一定有逆元)

用二项式定理展开(1+x)^p

 技术分享图片

除了第一项和最后一项,中间项的组合数在模p意义下是0

所以

技术分享图片

 这张图是盗来的http://www.cnblogs.com/owenyu/p/6724560.html

技术分享图片 

 

 

#include<cstdio>
using namespace std;
typedef long long LL;
LL f[100001];
void pre(int p)
{
    f[0]=1;
    for(int i=1;i<=p;i++) f[i]=f[i-1]*i%p;
}
int pow(LL a,int b,int p)
{
    LL r=1;
    while(b)
    {
        if(b&1) r*=a,r%=p;
        b>>=1; a*=a; a%=p; 
    }
    return r;
}
int C(int n,int m,int p)
{
    if(m>n) return 0; //如果m>n,那么原来的m<n-p,即m与n之间至少有一个p的倍数,那么结果为0 
    return f[n]*pow(f[m]*f[n-m],p-2,p)%p;
}
/*int Lucas(int n,int m,int p)
{
    if(!m) return 1;
    return (C(n%p,m%p,p)*Lucas(n/p,m/p,p))%p;
}*/
int Lucas(int n,int m,int p) //非递归版,上面是递归版 
{
    LL ans=1;
    for(;m;n/=p,m/=p) ans=ans*C(n%p,m%p,p)%p; 
    return ans;
}
int main()
{
    int T,n,m,p;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&p);
        pre(p);
        printf("%d\n",Lucas(n+m,m,p));
    }    
}

 

卢卡斯定理

标签:tail   cas   src   证明   技术分享   int   ima   组合   namespace   

原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7358327.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!