• [模板]卢卡斯定理/扩展卢卡斯定理


    卢卡斯定理

    用于求 n,m,p<1e5 p为素数 的C(n,m)%p

    Lucas(n,m,p)=C(n%p,m%p)×Lucas(n​/p,m/p,p)

    公式中的组合数部分预处理出阶乘然后求逆元算,后半部分递归解决,递归边界为m=0。

    #include<bits/stdc++.h>
    #define N 100010
    using namespace std;
    typedef long long ll;
    ll a[N];
    int p;
    ll pow(ll y,int z,int p){
        y%=p;ll ans=1;
        for(int i=z;i;i>>=1,y=y*y%p)if(i&1)ans=ans*y%p;
        return ans;
    }
    ll C(ll n,ll m){
        if(m>n)return 0;
        return ((a[n]*pow(a[m],p-2,p))%p*pow(a[n-m],p-2,p)%p);
    }
    ll Lucas(ll n,ll m){
        if(!m)return 1;
        return C(n%p,m%p)*Lucas(n/p,m/p)%p;
    }
    
    int main(){
        int T=read();
        while(T--){
            cin>>n>>m>>p;
            a[0]=1;
            for(int i=1;i<=p;i++)a[i]=(a[i-1]*i)%p;
            cout<<Lucas(n+m,n)<<endl;
        }
    }
    洛谷p3807

    扩展卢卡斯定理

    用于求n,m,p<1e18 p的唯一分解中的每一项都小于1e6 的C(n,m)%p

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    ll n,m,mod;
    inline ll pow(ll base,ll x,ll p){
        ll ans=1;
        while(x){
            if(x&1) ans=ans*base%p;
            base=base*base%p;
            x>>=1;
        }
        return ans;
    }
    inline ll exgcd(ll a,ll b,ll &x,ll &y){
        if(!b){
            x=1;y=0;
            return a;
        }
        ll r=exgcd(b,a%b,x,y);
        ll t=x;
        x=y;
        y=t-a/b*y;
        return r;
    }
    inline ll inv(ll a,ll b){
        ll x,y;
        return exgcd(a,b,x,y)==1?(x+b)%b:-1;
    }
    inline ll CRT(ll x,ll p){return x*inv(mod/p,p)%mod*mod/p%mod;}
    inline ll fac(ll x,ll p,ll pp){
        if(!x) return 1;
        ll res=1;
        for(int i=2;i<=p;i++) if(i%pp) res=res*i%p;
        res=pow(res,x/p,p);
        for(int i=2;i<=x%p;i++) if(i%pp) res=res*i%p;
        return res*fac(x/pp,p,pp)%p;
    }
    inline ll C(ll n,ll m,ll p,ll pp){
        ll fn=fac(n,p,pp),fm=fac(m,p,pp),fnm=fac(n-m,p,pp);
        ll k=0;
        for(ll i=n;i;i/=pp) k+=i/pp;
        for(ll i=m;i;i/=pp) k-=i/pp;
        for(ll i=n-m;i;i/=pp) k-=i/pp;
        return fn*inv(fm,p)%p*inv(fnm,p)%p*pow(pp,k,p)%p;
    }
    inline ll exlucas(ll n,ll m){
        ll t=mod,ans=0;
        for(int i=2;i*i<=mod;i++)
            if(t%i==0){
                ll p=1;
                while(t%i==0) p*=i,t/=i;
                ans=(ans+CRT(C(n,m,p,i),p))%mod;
            }
        if(t>1) ans=(ans+CRT(C(n,m,t,t),t)%mod);
        return ans%mod;
    }
    int main(){
        cin>>n>>m>>mod;
        cout<<exlucas(n,m);
    }
    洛谷p4720
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    ll mod;
    inline ll pow(ll base,ll x,ll p){
        ll ans=1;
        while(x){
            if(x&1) ans=ans*base%p;
            base=base*base%p;
            x>>=1;
        }
        return ans;
    }
    inline ll exgcd(ll a,ll b,ll &x,ll &y){
        if(!b){
            x=1;y=0;
            return a;
        }
        ll r=exgcd(b,a%b,x,y);
        ll t=x;
        x=y;
        y=t-a/b*y;
        return r;
    }
    inline ll inv(ll a,ll b){
        ll x,y;
        return exgcd(a,b,x,y)==1?(x+b)%b:-1;
    }
    inline ll CRT(ll x,ll p){return x*inv(mod/p,p)%mod*mod/p%mod;}
    inline ll fac(ll x,ll p,ll pp){
        if(!x) return 1;
        ll res=1;
        for(int i=2;i<=p;i++) if(i%pp) res=res*i%p;
        res=pow(res,x/p,p);
        for(int i=2;i<=x%p;i++) if(i%pp) res=res*i%p;
        return res*fac(x/pp,p,pp)%p;
    }
    inline ll C(ll n,ll m,ll p,ll pp){
        ll fn=fac(n,p,pp),fm=fac(m,p,pp),fnm=fac(n-m,p,pp);
        ll k=0;
        for(ll i=n;i;i/=pp) k+=i/pp;
        for(ll i=m;i;i/=pp) k-=i/pp;
        for(ll i=n-m;i;i/=pp) k-=i/pp;
        return fn*inv(fm,p)%p*inv(fnm,p)%p*pow(pp,k,p)%p;
    }
    inline ll exlucas(ll n,ll m){
        ll t=mod,ans=0;
        for(int i=2;i*i<=mod;i++)
            if(t%i==0){
                ll p=1;
                while(t%i==0) p*=i,t/=i;
                ans=(ans+CRT(C(n,m,p,i),p))%mod;
            }
        if(t>1) ans=(ans+CRT(C(n,m,t,t),t)%mod);
        return ans%mod;
    }
    int main(){
        int a,b;
        cin>>mod>>a>>b;
        ll sum=0;
        int c[7];
        for(int i=1;i<=b;i++){
            cin>>c[i];
            sum+=c[i];
        }
        if(sum>a){
            cout<<"Impossible"<<'
    ';
            return 0;
        }
        ll ans=1;
        for(int i=1;i<=b;i++){
            ans=ans*exlucas(a,c[i]);
            ans%=mod;
            a-=c[i];
        }
        cout<<ans;
    }
    洛谷p2183
  • 相关阅读:
    职场利器:说服力书籍排行榜
    经商必读的6本书推荐
    有关企业文化的书籍推荐
    创业书籍推荐
    企业文化建设的基本内容和主要步骤
    沟通书籍排行榜推荐
    企业文化建设案例与方案分享
    如何提高个人领导力?
    Project Recording: Date and Factory Date[转载]
    SAP Control framework–实例
  • 原文地址:https://www.cnblogs.com/xutianshu/p/10839753.html
Copyright © 2020-2023  润新知