欧几里得算法应用汇总

资料链接:例题  详解

//求最大公约数gcd(a,b)
int gcd(int a,int b)
{
    return !b?a:gcd(b,a%b);
}
//最小公倍数lcm(a,b)
int lcm(int a,int b)
{
    return a*b/gcd(a,b);
}
//扩展欧几里得算法:求线性方程ax+by=gcd(a,b)
int ex_gcd(int a,int b,int& x,int& y)
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    int g=ex_gcd(b,a%b,x,y);//g为最大公约数
    int tmp=x;
    x=y;
    y=tmp-a/b*y;
    return g;
}
//若求ax+by=m,m|gcd(a,b),
//先求ax0+by0=gcd(a,b),x=x0*m/gcd(a,b),y=y0*m/gcd(a,b);
//若ax0+by0=gcd(a,b);
//任意解为x=x0+b/gcd(a,b)*t,y=y0-a/gcd(a,b)*t;
结论1:
设a,b,c为任意整数,g = gcd(a, b),方程a * x + b * y = g的一组解是(x0, y0),则对于方程a * x + b * y = c,当c是g的倍数时,
其解为(x0 * c / g, y0 * c / g);当c不是g的倍数时无整数解。
结论2:
设a,b,c为任意整数,若方程a * x + b * y = c的一组整数解为(x0, y0),则它的任意解都可以写成(x0 + k * b', y0 - k * a'),
其中a' = a / gcd(a, b), b' = b / gcd(a, b),k取任意整数。
求解模线性方程:
结论:a ≡ b (mod n)的充要条件是:a - b是n的整数倍。
输入整数a,b,n,解方程a * x ≡ b (mod n)。
原方程可理解为:a * x - b是n的整数倍,设这个倍数为n,则a * x - n * y = 
b ,由扩展欧几里得结论1,当且仅当 b  % g == 0时,方程有解(其中g = gcd(a, n)。这样得到x = (x0 *  b  / g) % n(其中x0为扩展欧几里得算法求a * x + n * y = gcd(a, n)得到的一个解),需要说明的是,如果x是方程的解,那么满足x ≡ x' (mod n)的x'也是方程的解。
特别地:
当b = 1时,a * x ≡ 1(mod n)的解称为a关于模n的逆,类似于实数运算中“倒数”的概念。

根据上面的讨论,方程a * x - n * y = 1要有解,1必须是gcd(a, n)的倍数,因此a与n必须互素(即gcd(a, n) = 1)。所以当gcd(a, n) = 1时,该方程有解,否则方程无解。

void egcd(LL a, LL b, LL &x, LL &y, LL &G)
{
	if(!b)
	{
		G = a;
		x = 1;
		y = 0;
	}
	else
	{
		egcd(b, a%b, y, x, G);
		y -= x*(a/b);
	}
}
egcd(a, M, x, y, G);
return G == 1? (x+M)%M: -1LL;

你可能感兴趣的:(欧几里得算法应用汇总)