标签:
欧几里德算法(求最大公约数):
LL gcd(LL a, LL b)
{
return b == 0? a : gcd(b, a%b);
}
顺便写下求最小公倍数(lcm)
LL lcm(LL a, LL b)
{
return a*b/gcd(a, b);
}
朴素的欧几里德:
gcd(a, b) = gcd(b, a%b);
扩展欧几里德算法:
LL extend_gcd(LL a, LL b, LL &x, LL &y)
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
else
{
LL r = extend_gcd(b, a%b, y, x);
y -= x*(a/b);
return r;
}
}
该算法一般有三种应用:
应用1:
通解: 通过上面的第二点可知, 设a, b, c为任意整数, 若方程ax + by = c的一组整数解为(x0, y0), 则它的任意整数解都可以写成(x0+kb‘, y0-ka‘) (a‘ = a/gcd(a, b), b‘ = b/gcd(a, b), k取任意整数);所以(x0+kb‘, y0-ka‘)就是不定方程的通解.
特解:利用extend_gcd()可以求得一组解(x, y), 令 ans = extend_gcd(), 特解就等于c*x/ans.
最小解:在实际问题当中,需要的往往是最小整数解,可以通过下面的方法求出最小整数解:
令t = b/gcd(a, b),x是方程a*x + b*y = n的一个特解,则x = c*x/ans, xmin = (x % t + t) % t, y = (c-a*x)/b.
一道采用扩展欧几里德算法的题: poj 1061--青蛙的约会
应用2:
LL cal(LL a, LL m, LL c)
{
LL x, y;
LL ans = extend_gcd(a, m, x, y);
if(c%ans==1)
return -1;
x *= c/ans;
m /= ans;
m = abs(m);
LL sum = x%m; //求解最小解
if(sum <= 0)
sum += m; //保证最小解非负
return sum;
}
应用3:
//乘法逆元:ax≡1(mod m)
//a对于m的乘法逆元模板
LL cal(LL a, LL m)
{
LL x, y;
LL ans = extend_gcd(a, m, x, y);
if(1%ans==1)
return -1;
x *= 1/ans;
m = abs(m);
LL sum = x%m;
if(sum <= 0)
sum += m;
return sum;
}
标签:
原文地址:http://www.cnblogs.com/xl1164191281/p/5719559.html