数论基础(持续更新)

一、欧几里得算法

又称辗转相除法,设a,b为整数,gcd(a,b)=gcd(b,a mod b);

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

二、线性组合

定理:gcd(a,b)是a,b的最小正线性组合,即gcd(a,b)=a*x+b*y;


三、扩展欧几里得算法

问题:如何求二中的x,y?

思路:

①if b==0,a!=0->可取x=1,y=0

②if a*b!=0;

由于gcd(a,b)=a*x+b*y;gcd(b,a mod b)=b*x'+(a-(a/b)*b)*y';

由于gcd(a,b)==gcd(b,a mod b),可以得到递推式子:

x=y'

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

可以发现(x,y)->(x',y')与(a,b)->(b,a mod b)是同步的

所以稍微修改gcd函数,使得在求得最大公约数的同时,递归可以求得x,y的一组解

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

这里要特别说一下,如何的到x,y的通解。实际上,所有的(x0,y0)都可以得到无数组答案->(x0+b*k,y0-a*k)

但是这不是所有的答案,所有的答案应该是:(x0+b/gcd(a,b)*k,y0-a/gcd(a,b)*k)

四、扩展欧几里得算法求解不定方程

a*x+b*y=c有整数解的充要条件是gcd(a,b)|c

因为我们总可以得到gcd(a,b)=a*x'+b*y'

假如c=0(mod gcd(a,b)),那么只要等式两边同时乘以c/gcd(a,b),即得解

x=x'*c/gcd(a,b)

y=y'*c/gcd(a,b)

由于x*,y*有无数组,所以对应的x,y也有无数组

bool linear_equation(int a,int b,int c,int& x,int& y){
	int d=exgcd(a,b,x,y);
	if(c%d)return false;
	int k=c/d;
	x*=k;y*=k;
	return true;
}

五、扩展欧几里得算法求解同余方程

六、扩展欧几里得算法求解逆元

猜你喜欢

转载自blog.csdn.net/qq_41333528/article/details/80374350