算法讲解(数论应用)
模线性方程和线性方程组
1)欧几里得算法(gcd)
运用辗转相除法求两个数最大公约数(下方代码是递归的最简形式
原理来自于 gcd(a, b) = gcd(b , a%b)
int gcd(a, b)
{
return b == 0 ? a : gcd(b, a % b);
}
2)扩展欧几里得算法
在接触扩展欧几里得算法之前,我们可以先了解一下贝祖定理:
如果a、b是整数,那么一定存在整数x、y使得ax+by=mgcd(a,b)
也就是说面对ax+by=k这个方程,k一定是gcd(a,b)的整数倍
所以我们可以用传统的欧几里得算法来探究ax+by=k这个方程是否有解。但是,如果我们还想知道的更多,比如ax+by=k这个方程在有解的情况下解具体是多少的话。就需要用到扩展欧几里得算法,也就是我们常说的扩展gcd。(这里所说的解是一组通解)
用x和y来表示这一组通解的话(这个地方不懂的建议学习一下不定方程的通解)
x = x + (b/gcd)*t
y = y – (a/gcd)*t
这个地方可能会有两个问题
1>为什么b/gcd和a/gcd不用b和a代替
b/gcd和a/gcd分别是b,a的因子,最差的情况就是相等,所以/gcd后能取到的解更多
2>问什么b/gcd和a/gcd是最小的取值
因为这两个数互质,所以这是最小的满足的值
所以,我们只需要在传统欧几里得算法上面进行改进就可以了,这里直接给代码
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 temp=y; //把x y变成上一层的
y=x-(a/b)*y;
x=temp;
return r; //得到a b的最大公因数
}
3)关于同余以及求模线性方程的方法
什么是同余
给定一个正整数m,如果两个整数a和b满足(a-b)能够被m整除,即(a-b)/m得到一个整数,那么就称整数a与b对模m同余,记作a≡b(mod m)。
求解线性方程
1.当且仅当d|b时,方程ax = b(mod n)有解。d=gcd(a,n)
2.ax = b(mod n) 或者有d个不同解,或者无解。
3.令d=gcd(a,n) 假定对整数x’, y’, 有d = ax’ + ny’, 如果d | b, 则方程ax = b(mod n)有一个解的值为x, 满足:x=x‘(b/d)(mod n)
4.假设方程ax = b(mod n)有解, x0是方程的任意一个解, 则方程对模n恰有d个不同的解,
分别为:xi = x + i * (n / d), 其中 i = 1,2,3…d - 1
伪代码以及模板为:
MODULAR_LINEAR_EQUATION_SOLVER(a,b,n)
(d,x',y')=EXTENDED_EUCLID