常用数论模板

---恢复内容开始---

几种乘法逆元的求法:

这里假设mod=1e9+7

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<stack>
#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
#define ri register int
typedef long long ll;

inline ll gcd(ll i,ll j){
	return j==0?i:gcd(j,i%j);
}
inline ll lcm(ll i,ll j){
	return i/gcd(i,j)*j;
}
inline void read(int &x){
    char ch=x=0;
    while(!isdigit(ch))
        ch=getchar();
    while(isdigit(ch))
        x=x*10+ch-'0',ch=getchar();
}
const int mod=1e9+7;
const int maxn=1e5+5;
int ivn[maxn];
void egcd(int a,int b,int & x,int & y){//拓展欧几里得求a的逆元(为X), 
	if(b==0){
		x=1;
		y=0;
		return ;
	}
	egcd(b,a%b,x,y);
	int x1=x;
	int y1=y;
	x=y1;
	y=(x1-(a/b)*y1+mod)%mod;
	return ;
}
int qpow(int a,int b){ //利用费马定理求a逆元 
	int ans=1;
	while(b){
		if(b&1)ans=(ll)ans*a%mod;
		a=(ll)a*a%mod;
		b/=2;
	}
	return ans;
}
void work(){//线性求1~(mod-1)的逆元 
	ivn[1]=1;
	for(int i=2;i<=maxn;i++){
		ivn[i]=(ll)(mod-mod/i)*ivn[mod%i]%mod;
	}
}
int main(){
	int ivn1,ivn2;
	int a;
	egcd(2,mod,ivn1,a);
	ivn2=qpow(2,mod-2);
	cout<<ivn1<<" "<<ivn2<<endl;
	int n;
	work();
	while(~scanf("%d",&n)){
		printf("%d\n",ivn[n]);
	}
	return 0;
}

  

 欧拉函数:

int euler(int n){//求某个数的欧拉函数 
    int ret=n;
    for(int i=2;i<=sqrt(n);i++){
        if(n%i==0){
            ret=ret/i*(i-1);
            while(n%i==0)
            n/=i;
        }
    }
    if(n>1)ret=ret/n*(n-1);
    return ret;
}
void findphi(){//埃拉托斯特尼筛求欧拉函数
    phi[1]=1;
    for(int i=2;i<=1e5;i++){
        phi[i]=i;
    }
    for(int i=2;i<=1e5;i++){
        if(phi[i]==i)
        for(int j=i;j<=1e5;j+=i){
            phi[j]=phi[j]/i*(i-1);
        }
    }
}
void eulorphi(){//欧拉筛求欧拉函数 
    phi[1]=1;
    memset(vis,0,sizeof(vis));
    for(int i=2;i<=1e5;i++){
        if(vis[i]==0){
            pri[++pri[0]]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=pri[0]&&i*pri[j]<=1e5;j++){
        //    cout<<i<<" "<<pri[j]<<" "<<phi[i]<<" "<<phi[pri[j]]<<endl;
                vis[i*pri[j]]=1;    
                if(i%pri[j]==0){
                    phi[i*pri[j]]=phi[i]*pri[j];
                    break;
                }
                phi[i*pri[j]]=phi[i]*phi[pri[j]];
            }
    }
    for(int i=1;i<=100;i++){
        output(phi[i]);
        cout<<" ";
        if(i%10==0)
        cout<<endl;
    }
}

素数筛:

void ai(){//埃氏筛 
	int vis[maxn];
	memset(vis,0,sizeof(vis));
	int ss[maxn];
	int cnt=0;
	for(int i=2;cnt<=100;i++){
		if(vis[i]==0){
			ss[++cnt]=i;
			for(int j=i*i;j<=maxn;j+=i){
				vis[j]=1;
			}
		}
	}
	for(int i=1;i<=100;i++){
		output(ss[i]);
		printf(" ");
		if(i%10==0){
			printf("\n");
		}
	}
} 

  

void eulorpri(){//欧拉筛
	memset(vis,0,sizeof(vis));
	for(int i=2;i<=1e5;i++){
		if(vis[i]==0){
			pri[++pri[0]]=i;
		}
		for(int j=1;j<=pri[0]&&i*pri[j]<=1e5;j++){
			vis[i*pri[j]]=1;
			if(i%pri[j]==0)//代码核心
			break;
		}
	}
	for(int i=1;i<=100;i++){
		output(pri[i]);
		cout<<" ";
		if(i%10==0)
		cout<<endl;
	}
}

  

posted @ 2019-03-17 16:23  风雨兼程-zhi  阅读(148)  评论(0编辑  收藏  举报