简单数论

1.gcd&exgcd

1.gcd: 辗转相除。

int gcd(int x,int y){
    if(y==0) return x;
    return gcd(y,x%y);
}

2.exgcd:
裴蜀定理:对于任意正整数a,b,一定存在非零数对(x,y),满足ax+by=gcd(a,b).
(gcd(a,b)=gcd(b,a\%b))
(x',y')是方程$ by'+ (a % b) x' =gcd(b,a%b) $的解

$ by'+ (a % b) x' =gcd(a,b) $

$ by'+ (a-b(a/b)) x' =gcd(a,b) $

$ ax'+by'-b(a/b)x' =gcd(a,b) $

$ ax'+b(y'-(a/b)x') =gcd(a,b) $

(x=x',y=y'-(a/b)x')

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

2.欧拉函数

(phi(n)) 表示小于等于 (n) 且与 (n) 互质的数的个数。
(phi(n)=nprod_{p|n} (1-frac 1 p))
特别地,(phi(1)=1).
感性理解一下。证明不会

1.(O(sqrt n)) 筛质因数求欧拉函数。
@[墨染空] 的代码

int phi = x;
for(int j = 2; j * j <= x; j++){
    if(x % j == 0){
            phi = phi / j * (j - 1);
            while(x % j == 0) x /= j; 
        }
}
if(x > 1) phi = phi / x * (x - 1);

2.(O(n)) 线性筛出(1-n)(phi (i))
由定义可知,(phi (p) =p-1)
如果(p|x,phi (px)=p phi(x))
否则,(phi (px)=(p-1) phi(x))
证明不会
这份是我的代码

phi[1]=1;
for(int i=2;i<=n;i++){
	if(!vis[i]) p[++cnt]=i,phi[i]=i-1;
	for(int j=1;j<=cnt&&i*p[j]<=n;j++){
		vis[i*p[j]]=1;
		if(i%p[j]==0){
			phi[i*p[j]]=phi[i]*p[j];
			break;
		}
		phi[i*p[j]]=phi[i]*(p[j]-1);
	}
}

3.逆元

两种。

1.费马小定理(p为质数)
(a^{p-1} equiv 1 mod p)
(a^{p-2} equiv frac 1 p mod p)
(inv(x)=x^{p-2} mod p)
快速幂。

2.exgcd
(xinv(x) equiv 1 mod p)
(s=inv(x))
(xs equiv 1 mod p)
(xs+pt=1)
exgcd。

4.crt&excrt

crt不会 反正excrt挺好的。
模板题
现在有n个形如$ x equiv a_i pmod {b_i}$的方程

假设前k-1个方程的最小正整数解是(ans_{k-1},)
(M=gcd(b_1,b_2,……,b_{k-1}))

(ans_k=ans_{k-1}+xM(x为整数))

(ans_{k-1}+xM equiv a_k pmod {b_k})

(∴Mxequiv {{a_k}-{ans_{k-1}}} pmod {b_k})

(Mx+{b_k}y={{a_k}-{ans_{k-1}}})

exgcd。
题目的a,b读入是反的,注意。 还有记得开longlong。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int n;
LL ans,M=1; 
LL gcd(LL x,LL y){ return y?gcd(y,x%y):x; } 
LL lcm(LL x,LL y){ return x*y/gcd(x,y); }
LL exgcd(LL A,LL B,LL &x,LL &y){
	if(!B){ x=1,y=0;return x; }
	else{
		LL d=exgcd(B,A%B,y,x);
		y-=A/B*x;return d;
	}
} 
void crt(LL A,LL B){
	LL a=M,b=B,c=((A-ans)%B+B)%B,x,y;
	LL g=exgcd(a,b,x,y);
	if(c%g) return;
	x=((x*(c/g))%B+B)%B;ans+=x*M;
	M=lcm(M,B);ans=(ans%M+M)%M;
} 
int main(){
	scanf("%d",&n);
	LL a,b;
	for(int i=1;i<=n;i++)
		scanf("%lld%lld",&a,&b),crt(b,a);
	printf("%lld
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/zdsrs060330/p/13912609.html