zoukankan      html  css  js  c++  java
  • 扩展Lucas

    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,x,y);
        return (x%b+b)%b;
    }
    LLL fac(LLL n,LLL x,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,x,p)%p;//当前的不含因子x的乘积乘以递归下去求的剩余阶乘部分的结果
    }
    LLL cal(LLL n,LLL m,LLL x,LLL p)//x是当前质数,p是题目要求质数 
    {
        LLL N=fac(n,x,p),M=fac(m,x,p),Z=fac(n-m,x,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 m,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,m,t,t),p,t))%p;
        printf("%lld
    ",ans%p);
    }
    int main()
    {
        LLL n=read(),m=read(),p=read();
        exlucas(n,m,p);
    }
    exLucas
  • 相关阅读:
    洛谷 1996——约瑟夫问题(线性数据结构)
    洛谷 1219——[USACO 1.5] 八皇后(深度优先搜索)
    洛谷 1162——填涂颜色(广度优先搜索)
    洛谷 1803——凌乱的yy(贪心)
    洛谷 1094——纪念品分组(贪心)
    洛谷 1223——排队接水(贪心)
    洛谷 1028——[USACO 1.3]混合牛奶 Mixing Milk
    洛谷 1181——数列分段Section I(贪心)
    洛谷 1090——合并果子(贪心)
    洛谷 1012——拼数(字符串处理)
  • 原文地址:https://www.cnblogs.com/yyys-/p/11311858.html
Copyright © 2011-2022 走看看