同余与同余方程(扩展欧几里得)

同余应该是数论中比较基础的一个东西了。感觉挺重要的。。。高中没学好到大学来补了。

涉及3个数,a,b,m。就是a % m == b % m.

可以写成:a \equiv b(mod m)。

一、同余及其一些性质

同余有一些显然性质,有的时候会有很大功效。(不列举了,一般书上都有的)。

例1:给定整数n,m,k.求n^m mod k的值。m,n,k*k为长整型范围内的自然数。

这样的题根据数据类型有不同的解法:

这里m还在数据类型可表示的范围内,当m极大时,就要用到欧拉降幂这个东西。

这里说一下m还在数据类型可存储范围内的做法。

n^1  \equiv n (mod k)

n^2  \equiv (n mod 7) * (n mod 7) mod 7

n^4  \equiv (n^2 mod 7) * (n^2 mod 7) mod 7

......

将m进行二进制分解,然后递推得到结果,当然递归也是可以的。

二、同余方程

GCD:最大公约数  辗转相除法 一句话: 

int GCD(int x, int y){
    return y == 0 ? x : GCD(y, x % y);
}

LCM:   最小公倍数

int LCM(int x, int y){
    return x * y / GCD(x, y);
}

扩展欧几里得算法:

   这个算法是用来求已知a,b时,求一组p,q使得p*a+q*b=GCD(a,b)。由某些定理,解一定存在。

  因为GCD(a,b) = GCD(b, a%b)。

 p*a + q*b = GCD(a,b) = GCD(b, a % b)

  即:p*a + q*b = p * b + q * (a % b) = p * b + q * (a - a / b * b) = q * a + (p - a/b * q) * b.

a,b都在不停的减小,最后b减小到0, 可以得出p=1,q=0。然后递归回去,得到最终的p,q。

同余方程:

    求一组x,y使得a*x+b*y=c。首先该方程等价于a*x \equivc(mod b),有整数解的充分必要条件是c % GCD(a,b)=0。

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

同余方程:

   求关于x的同余方程a * x = c(mod b)的解。

定理一:该同余方程等价于a * x + b * y = c。有解的充分必要条件是c % GCD(a, b) = 0.我们可以先用扩展欧几里得算法得到

a * x + b * y = GCD(a, b)的一组解(x0,y0).然后两边同除GCD(a, b),同乘c,得到a * x0 * c / GCD(a, b) + b * y0 * c/GCD(a, b) = c

这样就找到了方程的一组解(x0 * c / GCD(a, b), y0 * c / GCD(a, b))。

定理二:若GCD(a, b)=1,且x0,y0为a*x + b * y 的一组解,则该方程的任一解可表示为x = x0 + b * t, y = y0 - a * t,对任一整数t都成立。

往往我们要找x的最小整数解,那么 t = b / GCD(a, b), x = (x % t + t) % t;此时x即为最小整数解。

bool TY(int a, int b, int c, int &x, int &y){
    int d = exgcd(a, b, x, y);
	if(c % d != 0) return 0;
	int k = c / d;
	x *= k;
	y *= k;
	return 1;
}//x是全局变量,返回意义不大,为了方便处理无解的情况,把函数设为boo类型。

注意:求最小整数解时加上:

t = b / GCD(a, b),

x = (x % t + t) % t;

 

 

 

 

你可能感兴趣的:(数论)