zoukankan      html  css  js  c++  java
  • lucas和扩展lucas

    lucas

    作用:求C(n,m)(mod p){p∈Prime}

    定理:设n=sp+q,m=tp+r,C(n,m)=C(sp+q,tp+r)=C(s,t)*C(q,r);

    证明

    考虑组合数和二项式展开的系数的关系;

    C(sp+q,tp+r)即为(1+x)^(sp+q)中x^(tp+r)项的系数;

    展开(1+x)^(sp+q)

    (1+x)^(sp+q)=((1+x)^p)^s*(1+x)^q;

    (1+x)^p=∑C(p,i)x^i*1^(p-i)=∑C(p,i)x^i;当(0<i<p)时C(p,i)=p*(p-1)!/(i!*(p-i)!),在mod p的意义下,此式为0

    所以(1+x)^p=C(p,0)*x^0+C(p,p)*x^p=(1+x^p);

    所以(1+x)^sp+q=(1+x^p)^s*(1+x)^q=[∑C(s,i)x^(i*p)*1^(s-i)][∑C(q,j)x^j*1^(q-j)]=[∑C(s,i)x^(i*p)][∑C(q,j)x^j]

    此时x^(i*p+j)的系数为C(s,i)*C(q,j),所以x^(tp+r)的系数为C(s,t)*C(q,r)

    所以C(sp+q,tp+r)=C(s,t)*C(q,r);

    模板题https://www.luogu.org/problemnew/show/P3807

    #include<cstdio>
    #include<iostream>
    #include<ctype.h>
    #include<cmath>
    using namespace std;
    #define ll long long
    inline ll rd()
    {
        ll x=0,f=1;char c=getchar();
        while(!isdigit(c)){if(c=='-') f=-f;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return x*f;
    }
    inline ll ksm(ll x,ll n,ll mod){ll ans=1;for(;n;n>>=1,x=x*x%mod) if(n&1) ans=ans*x%mod;return ans;}
    inline ll C(int n,int m,int p)
    {
        if(n==m||!m) return 1;if(m>n) return 0;ll ans=1,g=1;
        for(int i=n-m+1;i<=n;i++) ans=ans*i%p;
        for(int i=1;i<=m;i++) g=g*i%p;return ksm(g,p-2,p)*ans%p;
    }
    inline ll lucas(int n,int m,int p)
    {
        if(n==m||!m) return 1;if(m>n) return 0;
        return C(n%p,m%p,p)*lucas(n/p,m/p,p)%p;
    }
    int main()
    {
        for(int i=rd(),n,m,p;i;i--) n=rd(),m=rd(),p=rd(),printf("%lld
    ",lucas(n+m,m,p));
    }

    扩展lucas

    作用:求C(n,m)(mod p)

    {中国剩余定理是指对于一系列同余方程{x=a1(mod w1)……x=an(mod wn)},其中mi互质,一个合法解为{设W=Πwi,ti=(W/wi)在模wi意义下的逆元;ans=∑ai*ti*(W/wi);}

    1:设p=Πbi^ci;

    2:构造同余方程组wi=bi^ci,ai=C(n,m)(mod wi),设inv(x,y)表示x在模y意义下的逆元。

    3:解同余方程组。

    模板题:https://www.luogu.org/problemnew/show/P4720

    #include<cstdio>
    #include<iostream>
    #include<ctype.h>
    #include<cmath>
    using namespace std;
    #define ll long long
    inline ll rd()
    {
        ll x=0,f=1;char c=getchar();
        while(!isdigit(c)){if(c=='-') f=-f;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return x*f;
    }
    ll exgcd(ll a,ll b,ll &x,ll &y)
    {
        if(!b){x=1;y=0;return a;}
        ll t=exgcd(b,a%b,x,y),w=x;x=y;y=w-a/b*x;return t;
    }
    ll inv(ll a,ll mod)
    {
        ll x,y,d=exgcd(a,mod,x,y);
        return d==1?(x%mod+mod)%mod:-1;
    }
    ll ksm(ll x,ll n,ll mod){ll ans=1;x%=mod;for(;n;n>>=1,x=x*x%mod)if(n&1)ans=ans*x%mod;return ans;}
    ll Mul(ll n,int p,int g)
    {
        if(n<2) return 1;
        ll ans=1; if(n/p) for(ll i=1;i<p;i++) if(i%g) ans=ans*i%p;
        ans=ksm(ans,n/p,p);for(ll i=n%p;i>1;i--) if(i%g) ans=ans*i%p;return ans*Mul(n/g,p,g)%p;
    }
    ll C(ll n,ll m,int g,int k,int mod)
    {
        if(m>n) return 0;
        ll a=Mul(n,k,g),b=Mul(m,k,g),c=Mul(n-m,k,g),i,w=0; 
        for(i=n;i;i/=g) w+=i/g;for(i=m;i;i/=g) w-=i/g;for(i=n-m;i;i/=g)w-=i/g;
        ll ans=a*inv(b,k)%k*inv(c,k)%k*ksm(g,w,k)%k;ans=ans*(mod/k)%mod*inv(mod/k,k)%mod;return ans;
    }
    ll exlucas(ll n,ll m,int p)
    {
        ll ans=0,x=p;
        for(int i=2;i<=sqrt(x);i++)
            if(x%i==0)
            {
                int k=1;
                while(x>1&&x%i==0) x/=i,k*=i;
                ans=(ans+C(n,m,i,k,p))%p;
            }
        if(x>1) ans=(ans+C(n,m,x,x,p))%p;
        return ans;
    }
    int main()
    {
        ll n=rd(),m=rd(),p=rd();
        printf("%lld",exlucas(n,m,p));
    }
  • 相关阅读:
    AMD平台如何使用Android Studio官方的高性能模拟器
    Nginx安装SSL证书,开启HTTPS加密
    【English】20190429
    【Teradata】TD Unicode编码格式下varchar定义测试
    【Teradata TTU】Windows TTU安装工具列表
    【English EMail】2019 Q2 Public Holiday Announcement
    【English】20190428
    【张东武 老架一路74式第一段】第二式 金刚捣碓
    【影音制作】编辑视频
    【Teradata SQL】多行转一列函数TDStats.udfConcat
  • 原文地址:https://www.cnblogs.com/LWL--Figthing/p/10816290.html
Copyright © 2011-2022 走看看