数论板子

exgcd

__int128 exgcd(__int128 as,__int128 bs,__int128 &x,__int128 &y){
    if(bs==0){
        x=1;
        y=0;
        return as;
    }
    __int128 ans=exgcd(bs,as%bs,y,x);
    y-=(as/bs)*x;
    return ans;
}

a&c&lucas

long long c(long long x,long long y){
    if(x>y) return 0;
    return jc[y]%mod*fc[x]%mod*fc[y-x]%mod;
}
long long a(long long x,long long y){
    if(x>y) return 0;
    return jc[y]%mod*fc[y-x]%mod;
}
long long lcs(long long x,long long y){
    if(x==0) return 1;
    return c(x%mod,y%mod)%mod*lcs(x/mod,y/mod)%mod;
}
    jc[0]=jc[1]=1;
    inv[0]=inv[1]=1;
    fc[0]=fc[1]=1;
    for(long long i=2;i<=mod;i++){
        jc[i]=jc[i-1]*i%mod;
        inv[i]=((mod-mod/i*inv[mod%i])%mod+mod)%mod;
        fc[i]=fc[i-1]*inv[i]%mod;
    }

excrt

__int128 excrt(){
    __int128 aa=a[1],bb=b[1],x,y;
    for(int i=2;i<=n;i++){
        __int128 an=exgcd(aa,a[i],x,y);
        if((b[i]-bb)%an) return -1;
        x=(b[i]-bb)/an*x%(a[i]/an);
        bb=aa*x+bb;
        aa=aa/an*a[i];
        bb%=aa;
    }
    return (bb%aa+aa)%aa;
}

exlucas

#include<iostream>
#include<cstdio>
using namespace std;
#define ll long long 
ll poww(ll x,ll y,ll k){
    ll ans=1;
    x%=k;
    while(y){
        if(y&1ll){
            ans=(ans*x)%k;
        }
        y>>=1ll;
        x=(x*x)%k;
    }
    return ans;
}
ll ff(ll n,ll p,ll pk){
    if(n==0) return 1;
    ll x=1,y=1;
    for(ll i=1;i<=pk;i++){
        if(i%p){
            x*=i;
            x%=pk;
        }
    }
    x=poww(x,n/pk,pk);
    for(ll i=pk*(n/pk);i<=n;i++){
        if(i%p){
            y*=(i%pk);
            y%=pk;
        }
    }
    return ff(n/p,p,pk)*x%pk*y%pk;
}
ll gg(ll n,ll p){
    if(n<p) return 0;
    return gg(n/p,p)+(n/p);
}
void exgcd(ll a,ll b,ll &x,ll &y){
    if(b==0){
        x=1;
        y=0;
        return;
    }
    exgcd(b,a%b,x,y);
    ll z=x;
    x=y;
    y=z-y*(a/b);
}
ll inv(ll a,ll b){
    ll x,y;
    exgcd(a,b,x,y);
    return (x+b)%b;
}
ll cc(ll n,ll m,ll p,ll pk){
    ll zza=ff(n,p,pk),m1=inv(ff(m,p,pk),pk),m2=inv(ff(n-m,p,pk),pk);
    ll mm=poww(p,gg(n,p)-gg(m,p)-gg(n-m,p),pk);
    return zza*m1%pk*m2%pk*mm%pk;
}
ll exlucas(ll n,ll m,ll p){
    ll x=p,ans=0;
    for(ll i=2;i*i<=p;i++){
        if((x%i)==0){
            ll pk=1;
            while((x%i)==0){
                pk*=i;
                x/=i;
            }
            ll y=p/pk,z=cc(n,m,i,pk),mf=inv(y,pk);
            ans+=z*y*((mf+p)%p)%p;
            ans%=p;
        }
    }
    if(x!=1){
        ll y=p/x,z=cc(n,m,x,x),mf=inv(y,x);
        ans+=z*y*((mf+p)%p)%p;
        ans%=p;
    }
    return ans;
}
int main(){
    ll n,m,p;
    scanf("%lld%lld%lld",&n,&m,&p);
    printf("%lld",exlucas(n,m,p));
    return 0;
}
posted @ 2023-07-18 20:42  muzqingt  阅读(16)  评论(0编辑  收藏  举报