数论代码整理

Posted kylinbalck

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数论代码整理相关的知识,希望对你有一定的参考价值。

数论模板

此处均为代码,学习出门右转

一、公约数、公倍数

GCD
int gcd(int x,int y){
    return !y?x:gcd(y,x%y);
}
LCM
int lcm(int x,int y){
    return x/gcd(x,y)*y;
}
拓展欧几里得
int x,y;
int ex_gcd(int a,int b){
    if(!b){
        x=1,y=0;return a;
    }
    int temp=ex_gcd(b,a%b);
    x=y,y=temp-a/b*y;
    return temp;
}

二、筛素数

埃拉托色尼筛法
int cnt,prime[maxn];
bool not_pr[maxn];
void Get_Prime(int x){
    not_pr[1]=1;
    for(int i=2;i<=x;++i)
        if(!not_pr[i]){
            prime[++cnt]=i;
            for(int j=i*i;j<=x;j+=i) not_pr[j]=1;
        }
}
线性筛
int cnt,prime[maxn];
bool not_pr[maxn];
void Get_Prime(int x){
    not_pr[1]=1;
    for(int i=2;i<=x;++i){
        if(!not_pr[i]) prime[++cnt]=1;
        for(int j=1;j<=cnt&&i*prime[j]<=n;++j){
            not_pr[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}
(O(nlogn))时间内筛除n以内所有数的素因子
int cnt,prime[maxn],pre[maxn];
bool not_pr[maxn];
void Get_Prime(int x){
    not_pr[1]=1;
    for(int i=2;i<=x;++i){
        if(!not_pr[i]) prime[++cnt]=i;
        for(int j=1;j<=cnt;++j){
            if(i*prime[j]>x) break;
            not_pr[i*prime[j]]=1,pre[i*prime[j]]=j;
            if(i%prime[j]==0) break;
        }
    }
}
void Get_Ans(int x){
    for(int i=1;i<=x;++i){
        printf("%d:",i);
        int di=i;
        while(di!=1) printf("%d",prime[pre[di]]),di/=prime[pre[di]];
    }
}

三、求欧拉(φ)函数

埃拉托色尼筛法
int cnt,prime[maxn],phi[maxn];
bool not_pr[maxn];
void euler(int x){
    for(int i=1;i<=x;++i) phi[i]=i;
    for(int i=2;i<=x;++i)
        if(!not_pr[i]){
            prime[++cnt]=i,phi[i]=i-1;
            for(int j=i*i;j<=x;++j){
                not_pr[j]=1,phi[j]=phi[j]/i*(i-1);
         }
     }
}
欧拉筛
int cnt,prime[maxn],phi[maxn];
bool not_pr[maxn];
void euler(int x){
    phi[1]=1,not_pr[1]=1;
    for(int i=2;i<=x;++i){
        if(!not_pr[i]) prime[++cnt]=i,phi[i]=i-1;
        for(int j=1;j<=cnt;++j){
            if(i*prime[j]>x) break;
            not_pr[i*prime[j]]=1;
            if(!(i/prime[j])) phi[i*prime[j]]=phi[i]*prime[j];
            else phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
}

四、求逆元

单个数求逆元
int x,y;
int ex_gcd(int a,int b){
    if(!b){
        x=1,y=0;return a;
    }
    int temp=gcd(b,a%b);
    x=y,y=temp-a/b*y;
    return temp;
}
int cal(int a,int m){//ax%m==1,求最小的x
    int Gcd=gcd(a,m);
    if(1%Gcd!=0) return -1;
    x*=1/Gcd,m=abs(m);
    int ans=x%m;
    if(ans<=0) ans+=m;
    return ans;
}
快速幂求逆元

(p)为质数,(a^{(p-1)}~ mod ~p=1,a)的逆元为(a^{(p-2)});若(p)不是质数,(a^{phi[p]} ~mod ~p=1)(a)的逆元为(a^{phi[p]-1})

线性筛逆元
int inv[maxn];
void Get_inv(int x){
    inv[1]=1;
    for(int i=2;i<=x;++i) inv[i]=(p-p/i)*inv[p%i]%p;
}

快速幂

快速幂
int qpow(int x,int k){
    int a=1;
    while(k){
        if(k&1) a*=x;
        x*=x;
        k>>=1;
    }
    return a;
}
取膜快速幂
int powmod(int a,int k,int p){
    long long a=1;
    while(k){
        if(b&1) a=1ll*a*x%p;
        x=1ll*x*x%p;
        k>>=1;
    }
    return a;
}

组合数

void init_C(){
    for(int i=0;i<=n;++i) c[i][0]=1;
    for(int i=1;i<=n;++i)
            for(int j=1;j<=i;++j)
                    c[i][j]+=c[i-1][j-1]+c[i-1][j];
}

以上是关于数论代码整理的主要内容,如果未能解决你的问题,请参考以下文章

VS2015 代码片段整理

数论知识整理

常用python日期日志获取内容循环的代码片段

小程序各种功能代码片段整理---持续更新

PAT 数列的片段和简单数论

C#常用代码片段备忘