欧几里得算法、拓展欧几里得算法
欧几里得算法:$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$