最大公约数 & 最小公倍数

最大公约数(gcd)

求解方法:

欧几里得算法(辗转相除法):

\[\gcd(a,b)=\left\{ \begin{array}{rcl} \gcd(b,a \bmod b) & {b \neq 0}\\ a & {b = 0} \end{array} \right. \]

时间复杂度为\(O(logn)\)

递归形式:

int gcd(int a,int b){
	return b>0?gcd(b,a%b):a; 
}

非递归形式:

int gcd(int a,int b){
	while(b){int c=a;a=b;b=c%b;}
	return a;
}

更相减损术(辗转相减法):

适用于大整数求 \(\gcd\),比如高精度。

\[\gcd(a,b)=\left\{ \begin{array}{rcl} gcd(a-b,b) & {a \ge b}\\ a 或 b & {a = b}\\ gcd(a,b-a) & {a \le b}\\ \end{array} \right. \]

递归形式:

int gcd(int a,int b){
	if(a==b) return a;
	if(a<b) swap(a,b);
	return gcd(a-b,b);
}

非递归形式:

int gcd(int a,int b){
	while(a!=b){
		if(a<b) swap(a,b);a-=b;
	}
	return a;
}

扩展欧几里得算法(exgcd):

用于求解 \(ax+by=\gcd(a,b)\) 的一组整数特解,并可用于求解逆元和线性同余方程。
首先按照辗转相除法向下递归,
即:

\[ax+by=\gcd(a,b) \Rightarrow bx+(a \bmod b)y=\gcd(b,a \bmod b) \]

其中 \(a \bmod b = a-b \times \lfloor a/b \rfloor\),
那么,

\[ax+by=\gcd(a,b) \]

\[\Downarrow \]

\[bx+(a-b \times \lfloor a/b \rfloor)y=\gcd(b,a-b \times \lfloor a/b \rfloor) \]

\[\Downarrow \]

\[(a-b \times \lfloor a/b \rfloor)y+bx=\gcd(a,b) \]

\(ax+by=\gcd(a,b)\)\((a-b \times \lfloor a/b \rfloor)x'+by'=\gcd(a,b)\)
列出等式$$ax+by=(a-b \times \lfloor a/b \rfloor)x'+by'$$
解,得:\(\left\{\begin{aligned}x&=y'\\y&=x'-\lfloor a/b \rfloor\times y'\end{aligned}\right.\)
当递归进行到 \(b=0\) 时,可有一组解 \(\left\{\begin{aligned}x&=1\\y&=0\end{aligned}\right.\)
只需向上回溯时计算 \((x,y)\) 即可。

int exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	int g=exgcd(b,a%b,x,y);
	int t=x;x=y;y=t-a/b*y;
	return g;
}

应用:

\(ax+by=\gcd(a,b)\) 的通解

利用欧几里得定理我们求出了 \(ax+by=\gcd(a,b)\) 的一组特解 \((x_0,y_0)\),令其解集为 \(U\)
\(ax+by=\gcd(a,b)\) 变形得:

\[y=-\frac{a}{b}x+\frac{\gcd(a,b)}{b} \]

\(x_0,y_0\) 带入,得:

\[y_0=\frac{\gcd(a,b)-ax_0}{b} \]

可以得到 \((\gcd(a,b)-ax_0) \mid b\)
可以推出 \((\gcd(a,b)-ax_0+lcm(a,b)) \mid b\)
可以得到:

\[y_1=\frac{\gcd(a,b)-ax_0+lcm(a,b)}{b}=y_0+\frac{a}{\gcd(a,b)} \]

此时对应的:

\[x_1=x_0-\frac{a}{\gcd(a,b)} \]

可以继续推出其他解:

\[U=\{(x,y)|x=x_0-\frac{a}{\gcd(a,b)}n,y=y_0+\frac{a}{\gcd(a,b)}n,n \in \Z\} \]

\(ax'+by'=c,(c\mid\gcd(a,b))\) 的解

我们可以从 \(ax+by=\gcd(a,b)\),推出 \(ax'+by'=c\) 的一组整数特解,其中 \(c\mid\gcd(a,b)\)
先用扩展欧几里得求出 \(ax+by=\gcd(a,b)\),的一组解\((x,y)\),再将整个方程乘 \(\frac{c}{\gcd(a,b)}\),得到 \(ax\frac{c}{\gcd(a,b)}+by\frac{c}{\gcd(a,b)}=c\)
即可得出 \(ax'+by'=c\) 的解为 \(\left\{\begin{aligned}x'=x\frac{c}{\gcd(a,b)}\\y'=y\frac{c}{\gcd(a,b)}\end{aligned}\right.\)
至于其他解,跟上面一样:

\[\left\{\begin{aligned}x'=x\frac{c}{\gcd(a,b)}-\frac{a}{\gcd(a,b)}n\\y'=y\frac{c}{\gcd(a,b)}+\frac{a}{\gcd(a,b)}n\end{aligned}\right. \]

其中 \(n\in \Z\)

二分法快速求最大公因数(binary gcd):

该算法快于欧几里得算法。

\[\gcd(a,b)=\left\{ \begin{array}{rcl} a或b & {a==b}\\ 2 \times \gcd(\frac{a}{2},\frac{b}{2}) & {a、b为偶数}\\ \gcd(\frac{a}{2},b) & {a为偶数、b为奇数}\\ \gcd(\frac{a-b}{2},b) & {a、b为奇数} \end{array} \right. \]

int binary_gcd(int a,int b){
	if(a==b) return a;
	if(((a&1)|(b&1))==0) return gcd(a>>1,b>>1)<<1;
	if((a&1)==0) return gcd(a>>1,b);
	if((b&1)==0) return gcd(a,b>>1);
	if(a<b) swap(a,b);
	return gcd((a-b)>>1,b);
}

最小公倍数(lcm)

求解方法

\[lcm(a,b)=\frac{a \times b}{\gcd(a,b)} \]

int lcm(int a,int b){
	return a*b/gcd(a,b);
}
posted @ 2026-07-03 20:06  LZYXT  阅读(14)  评论(0)    收藏  举报