关于数论

由于博主比较蒻
尚在学习
所以先鸽亿会

欧拉函数

code

欧拉筛

Elaina's code
int n,phi[N],prime[N],cnt;
bool pri[N];

void Euler(){
	mst(pri,1);
	phi[1]=1;
	for(int i=2;i<=n;i++){
		if(pri[i]){
			prime[++cnt]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=cnt;j++){
			int k=i*prime[j];
			if(k>n){
				break;
			}
			pri[k]=0;
			if(i%prime[j]==0){
				phi[k]=prime[j]*phi[i];
				break;
			}else{
				phi[k]=(prime[j]-1)*phi[i];
			}
		}
	}
}

欧拉

Elaina's code
int Euler(int n){
	int m=sqrt(n+0.5);
	int ans=n;
	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;
}

欧几里得

code

递归

Elaina's code
// 递归形式
int gcd(int x, int y) {
    return(y == 0 ? x : gcd(y, x%y));
}

非递归

Elaina's code
// 非递归形式
int gcd(int x, int y) {
    int r=x%y;
    while(r){
        x=y;
        y=r;
        r=x%y;
    }
    return y;
}

懒狗

Elaina's code

//懒狗形式
__gcd();

扩展欧几里得(exgcd)

code

Elaina's code
int exgcd(int a,int b,int &x,int &y){
	if(!b){
		x=1;
		y=0;
		return a;
	}
	int res=exgcd(b,a%b,x,y);
	int t=x;
	x=y;
	y=t-a/b*y;
	return res;
}

乘法逆元

code

费马小定理

Elaina's code
int qpow(int a,int n,int mod){//a^n%mod
	int ans=1;
	while(n){
		if(n&1){
			ans=ans*a%mod;
		}
		a=a*a%mod;
		n>>=1;
	}
	return ans;
}

int niyuan(int a,int p){
	return qpow(a,p-2,p);
}

欧拉定理

扩展欧几里得

线性

Elaina's code
    inv[0]=inv[1]=invv[0]=invv[1]=1;
    for(int i=2;i<=n+5;i++){
    	fact[i]=fact[i-1]*i%p;
    	invv[i]=(-p/i*invv[p%i])%p,inv[i]=inv[i-1]*invv[i]%p;//阶乘逆元
    	inv[i]=(p-p/i)*inv[p%i]%p;//逆元
	}

中国剩余定理

code

Elaina's code

int n,a[N],m[N],Mi[N],M=1,ans=0;
int exgcd(int a, int b, int &x, int &y){
    if (!b){
        x=1, y=0;
        return a;
    }
    int d=exgcd(b,a%b,x,y);
    int z=x;
    x=y;
    y=z-y*(a/b);
    return d;
}
signed main(){
    cin>>n;
    for(int i=1;i<=n;i++){ 
        cin>>m[i];
        M*=m[i];  
        cin>>a[i];
    }
    for(int i=1;i<=n;i++){
        Mi[i]=M/m[i];
        int x=0,y=0;
        exgcd(Mi[i],m[i],x,y);
        ans+=a[i]*Mi[i]*(x%m[i]+m[i]);
    }
    cout<<ans%M;
    return Elaina;
}

扩展中国剩余定理

code

点击查看代码
int n,m,bi[N],ai[N];

int mul(int a,int n,int mod){
	int res=0;
	while(n){
		if(n&1){
			res=(res+a)%mod;
		}
		a=(a+a)%mod;
		n>>=1;
	}
	return res;
}

int exgcd(int a,int b,int &x,int &y){
    if(b==0){x=1;y=0;return a;}
    int gcd=exgcd(b,a%b,x,y);
    int tp=x;
    x=y; y=tp-a/b*y;
    return gcd;
}

int excrt(){
    int x,y;
    int M=bi[1],ans=ai[1];
    for(int i=2;i<=n;i++){
        int a=M,b=bi[i],c=(ai[i]-ans%b+b)%b;
        int gcd=exgcd(a,b,x,y);
		int bg=b/gcd;
        if(c%gcd!=0) return -1;
        
        x=mul(x,c/gcd,bg);
        ans+=x*M;
        M*=bg;
        ans=(ans%M+M)%M;
    }
    return (ans%M+M)%M;
}


main(){
    n=read();
    for(int i=1;i<=n;i++){
    	bi[i]=read();ai[i]=read();
	}
	cout<<excrt();
    return Elaina;
}

卢卡斯定理

code

点击查看代码
//fact[]为阶乘 inv[]为逆元
int C(int n,int m,int mod){
	return n<m?0:fact[n]*inv(fact[m],mod)%mod*inv(fact[n-m],mod)%mod;
}

int Lucas(int n,int m,int mod){
	if(!m){
		return 1;
	}
	return (C(n%mod,m%mod,mod)*Lucas(n/mod,m/mod,mod))%mod;
}
posted @ 2024-04-13 17:00  Elaina_0  阅读(15)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end