欧几里得算法、拓展欧几里得算法
欧几里得算法:$gcd(a,b)=gcd(b,a%b)$
int gcd(int a,int b) {
if (b==0) return a;
return gcd(b,a%b);
}
快速欧几里得算法(更相减损术):$gcd(a,b)=gcd(b,a-b)$
#define ctz __builtin_ctzll
LL gcd(LL a,LL b) {
if(!a) return b;
if(!b) return a;
int t=ctz(a|b);
a>>=ctz(a);
do {
b>>=ctz(b) ;
if(a>b) swap(a,b);
b-=a;
} while(b);
return a<<t;
}
拓展欧几里得算法:解不定方程$ax+by=gcd(a,b)$
算$gcd(a,b)$时,
有$ax+by=gcd(a,b)$ $(1)$
算$gcd(b,a\%b)$时,
有$bx'+(a\%b)y'=gcd(b,a\%b)$ $(2)$
设$\lfloor \frac{a}{b} \rfloor=k$,有$a \% b = a-k\times b$
带入$(2)$,有$ay'+b(x'-ky')=gcd(a,b)$,
因为对于任意的$a,b$恒成立,所以有
$
\left\{\begin{matrix}
{y=x'-ky'}
\\ {x=y'}
\end{matrix}\right.
$
先求出$gcd$,每次求出当前的$x',y'$,然后更新上一步的。
int exgcd(int a,int b,int& x,int& y){
int ans;
if (b==0) {
x=1; y=0;
return a;
}
ans=exgcd(b,a%b,x,y);
int tx=x;
x=y; y=tx-a/b*y;
return ans;
}
最小公倍数和最大公约数的性质
$gcd(Fib_a,Fib_b)=Fib_{gcd(a,b)}$
$gcd(x^a-1,x^b-1)=x^{gcd(a,b)}-1$