求连个数的最大公约数gcd:
typedef long long ll;
const int MAXN = 10000 + 7;
ll gcd(ll a, ll b) {
return b ? gcd(b, a%b) : a;
}
欧几里得定理: gcd(a, b) = gcd(b, a%b);
gcd(a,b)=gcd(b,a)=gcd(-a,b)=gcd(|a|,|b|)
扩展欧几里德算法是用来在已知a, b求解一组x,y使得ax+by = Gcd(a, b) =r(解一定存在,根据数论中的相关定理)。扩展欧几里德常用在求解模线性方程及
方程组中。
假设:
a*x0 + b*y0 = gcd(a, b) = r
b*x1 + (a%b)*y1 = gcd(b, a%b) = r
......(依次递推)
b`*x + (a%b`)*y = gcd = r
当a%b`=0亦即递归终止时,不妨令x = 1, y = 0;则可以据此依次网上递推求出x1, y1; x0, y0, 又a%b = a - (a/b)*b 整除;则有:
b*x1 + [a - (a/b)*b]*y1 = r;
即a*y1 + b[x1 - (a/b)*y1] = r; 对比a*x0 + b*y0 = r 系数有:
x0=y1,y0=x1-(a/b)*y1;
typedef long long ll;
ll extend_Euclid(ll a, ll b, ll& x, ll&y) {
if(b == 0) {
x = 1;
y = 0;
return a;
}
ll ans = extend_Euclid(b, a%b, x, y);
ll tmp = x;
x = y;
y = tmp - a/b*y;
return ans;
}
求解线性方程:
bool linerEquation(ll a, ll b, ll c, ll& x, ll& y) {
ll d = extend_Euclid(a, b, x, y);
if(c % d) return false;
x *= d, y *= d;
return true;
}
利用拓展欧几里得求逆元:
首先模的运算性质:
ll inverseEle(ll a, ll b) { // a关于1模b的逆元
ll x, y;
extend_Euclid(a, b, x, y);
x = (x%b + b) % b;
return x;
}
// x关于1模m的逆元, x,m互质, x^(m-2) 则x的逆元为x^(m-2)
ll inverseElePlus(ll x, ll m) {
m -= 2;
ll ans = 1;
while(m) {
if(m & 1) ans *= x;
x *= x;
m >>= 1;
}
return ans;
}