[模板][数论][gcd+exgcd+sieve+power+euler_phi+euler_table+inv]

来源:互联网 发布:淘宝店铺详情尺寸 编辑:程序博客网 时间:2024/06/07 00:10

NOIP临近,,写写模板。。。


求逆元:
扩展欧几里得求逆元
适用范围:常数小,适合单个求逆元
限制:gcd(a,n)==1

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#define FROP "inv"#define LL long longusing namespace std;int n=100,mod=1e9+7,inv[105];void exgcd(int a,int b,int& d,int &x,int &y){    if(!b){d=a;x=1;y=0;}    else {exgcd(b,a%b,d,y,x);y-=x*(a/b);}}int main(){    freopen(FROP".out","w",stdout);    for(int i = 1; i <= n; i++)    {        int d,x,y;        exgcd(i,mod,d,x,y);//i mod mod 的逆元        inv[i]=(x%mod+mod)%mod;    }    for(int i = 1; i <= n; i++)        printf("%d,",inv[i]);    return 0;}

费马小定理求逆元
适用范围:若mod是,inv=a^(mod-2)
否则inv=a^(phi(mod)-1),,所有前提条件,a,与mod互素。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#define FROP "inv"#define LL long longusing namespace std;int n=100,mod=1e9+7,inv[105];int euler_phi(int n){    int ans=n;    int m= sqrt(n+0.5);    for(int i = 2; i <= m; i++)if(n % i==0)    {        ans=ans/i*(i-1);        while(n%i==0)n/=i;    }    if(n>1)ans=ans/n*(n-1);    return ans;}int power(int a,int b){    if(!b)return 1;    if(b==1)return a;    int p=power(a,b/2);    p=(LL)p*p%mod;    if(b%2)return p*a%mod;    return p;}int main(){    freopen(FROP".out","w",stdout);        int eul=euler_phi(mod);    for(int i= 1; i <= 100; i++)    {        printf("%d,",power(i,eul-1));    }    return 0;}

线性求逆元
没有限制,,表示爱上线性求逆元了。。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#define FROP "inv"#define LL long longusing namespace std;int n=100,mod=1e9+7,inv[105];int main(){    freopen(FROP".out","w",stdout);    inv[1]=1;    for(int i = 2; i <= n; i++)        inv[i]=(LL)(mod-mod/i)*inv[mod%i]%mod;    for(int i = 1;i <= n; i++)        printf("%d,",inv[i]);    return 0;}

gcd模板

int gcd(int a,int b){return b==0?a:gcd(b,a%b);}

筛法求素数

void sieve(int n){    int m = sqrt(n+0.5);    for(int i = 2; i <= m; i++)if(!vis[i])        for(int j = i*i; j <= n; j+=i)vis[j]=1;}int main(){    freopen(FROP".in","r",stdin);    freopen(FROP".out","w",stdout);    sieve(100);    for(int i = 1;i <= n; i++)        if(!vis[i])printf("%d,",i);    return 0;}

单数欧拉函数

int euler_phi(int n){    int ans=n;    int m= sqrt(n+0.5);    for(int i = 2; i <= m; i++)if(n % i==0)    {        ans=ans/i*(i-1);        while(n%i==0)n/=i;    }    if(n>1)ans=ans/n*(n-1);    return ans;}

求1-n的欧拉函数
O(nloglogn)

int phi[100];void euler_table(int n){    for(int i = 2; i <= n; i++)phi[i]=0;    phi[1]=1;    for(int i = 2; i <= n;i++)if(!phi[i])        for(int j= i; j <= n; j+=i)        {            if(!phi[j])phi[j]=j;            phi[j]=phi[j]/i*(i-1);        }}

快速幂

int power(int a,int b){    if(!b)return 1;    if(b==1)return a;    int p=power(a,b/2);    p=(LL)p*p%mod;    if(b%2)return p*a%mod;    return p;}

差不多了,还有些以后再说吧。。。

0 0