加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

扩展Lucas

发布时间:2020-12-14 05:10:56 所属栏目:大数据 来源:网络整理
导读:Lucas用于模数是质数的情况,如果模数不是质数,就要用到扩展卢卡斯 思想 把模数质因子分解 对于每一个pi^ki做一遍普通Lucas,最后中国剩余定理合并。 要理解的是过程 其实就是算fac的时间更优了(充分利用阶乘的性质就不用O(n)预处理) 结合代码会更好理

Lucas用于模数是质数的情况,如果模数不是质数,就要用到扩展卢卡斯


思想

把模数质因子分解

对于每一个pi^ki做一遍普通Lucas,最后中国剩余定理合并。

要理解的是过程

其实就是算fac的时间更优了(充分利用阶乘的性质就不用O(n)预处理)

结合代码会更好理解~

#include<bits/stdc++.h>
#define LLL long long
using namespace std;
LLL read()
{
    LLL f=1,x=0;char s=getchar();
    while(s<0||s>9){if(s==-)f=-1;s=getchar();}
    while(s>=0&&s<=9){x=x*10+s-0;s=getchar();}
    return x*f;
}
LLL quick(LLL a,LLL x,LLL p)
{
    LLL ans=1;
    while(x)
    {
        if(x&1) ans=ans*a%p;
        a=a*a%p;x>>=1;
    }
    return ans%p;
}
/*LL inv(LL x,LL p)
{
    return quick(x,p-2,p);
}*/
void exgcd(LLL a,LLL b,LLL &x,LLL &y)
{
    if(!b){x=1,y=0;return;}
    exgcd(b,a%b,x,y);
    LLL t=x;
    x=y;y=t-(a/b)*y;
}
LLL inv(LLL a,LLL b)
{
    LLL x,y;
    exgcd(a,b,y);
    return (x%b+b)%b;
}
LLL fac(LLL n,LLL p)
{
    if(!n) return 1;
    LLL ans=1;
    for(LLL i=1;i<=p;++i)
      if(i%x)ans=ans*i%p;//不含因子x
    ans=quick(ans,n/p,p);//有循环节,所以乘积用快速幂计算即可(整块的)
    for(LLL i=1;i<=n%p;i++)//未构成整块的 
      if(i%x)
        ans=ans*i%p;
    return ans*fac(n/x,p)%p;//当前的不含因子x的乘积乘以递归下去求的剩余阶乘部分的结果
}
LLL cal(LLL n,LLL m,LLL p)//x是当前质数,p是题目要求质数 
{
    LLL N=fac(n,p),M=fac(m,Z=fac(n-m,p);
    //计算出对于每一个质数的若干次方取模后的结果
    LLL cnt=0; 
    for(LLL i=n;i;i/=x)
      cnt+=i/x;
    for(LLL i=m;i;i/=x)
      cnt-=i/x;
    for(LLL i=n-m;i;i/=x)
      cnt-=i/x;
    LLL ans=quick(x,cnt,p)*N%p*inv(M,p)%p*inv(Z,p)%p;
    return ans%p;
}
LLL CRT(LLL a,LLL p,LLL x)
{
    return inv(p/x,x)*(p/x)%p*a%p;
}
void exlucas(LLL n,LLL p)
{
    LLL t=p,ans=0;
    for(LLL i=2;i*i<=p;++i)
    {
        LLL k=1;
        if(t%i)continue;
        while(t%i==0){k=k*i;t=t/i;}
        ans=(ans+CRT(cal(n,m,i,k),p,k))%p;
    }
    if(t>1)ans=(ans+CRT(cal(n,t,t),t))%p;
    printf("%lldn",ans%p);
}
int main()
{
    LLL n=read(),m=read(),p=read();
    exlucas(n,p);
}
exLucas

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读