Loading

数论——最大公因数

最大公因数

如果\(u|a,u|b\),而且\(u\)\(a,b\)的共同因数中最大的那个,则称u是ab的最大公因数,记作\((a,b)=u\)

  • \((a,b)=1\)\(a,b\)互素。
  • 对于\(a_1,a_2...a_n\),若\((a_i,a_j)=1\ (1\leq i<j\leq n)\)则它们两两互素。

辗转相除法

辗转相除法应该都学过,我们主要说它的数学原理。在这之前先看看算法。

\[a=bq_1+r_1\\ b=r_1q_2+r_2\\ r_1=r_2q_3+r_3\\ ...\\ r_{n-2}=r_{n-1}q_n+r_n \]

这个\(r_n\)就是最大公因数。

辗转相除的意思就是,如果\(a,b\)能被\(n\)整除,那么\(a\mod b\)同样也能被\(n\)整除。所以(a,b)=(b,r)。所以只要不断地递归求余,最后一个余数就是最大公因数。

下面给出C++实现。

// a must > b
int gcd(int a,int b){
	int r;
	while(r!=0){
		r=a%b;
		a=b;
		b=r;
	}
	return a;
}

int main(){
	cout << gcd(20,15) << endl;
}

辗转相除的意思就是,如果\(a,b\)能被\(n\)整除,那么\(a\mod b\)同样也能被\(n\)整除。所以只要不断地递归求余,最后一个余数必是最大公因数。

证明

\[如果 (a,b)=u,那么\\ \because u|a,u|b\\ \therefore a=su,b=tu\\ \therefore su=tuq+r\\ \therefore r=u(s-tq)\\ \therefore u|r \]

素因式分解

对于每个数,都能分解成若干个素因数的乘积。在找\((a,b)\)的时候,如果我们把\(a,b\)分解成若干素因数的乘积,那么对寻找最大公因数有些帮助。

\[a=18,b=24\\ a=2\times 3\times 3 = 2^1\times 3^2\\ b=2\times 2\times 2 \times 3=2^2\times 3^1 \]

然后我们分别取每个素因数里指数最小的那个(必要时可以出现零指数),并乘起来,结果就是最大公因数。

\[(a,b)=2^1\times 3^1 = 6 \]

给出一般公式

\[a=p_1^{a_1}\times p_1^{a_2} \times ... \times p_n^{a_n}\\ b=p_1^{b_1}\times p_1^{b_2} \times ... \times p_n^{b_n}\\ (a,b)=p_1^{min(a_1,b_1)}\times p_2^{min(a_2,b_2)}\times ... \times p_n^{min(a_n,b_n)} \]

使用素因式分解还能寻找最小公倍数。

最小公倍数

如果\(a|c\)\(b|c\),并且\(c\)是所有满足的整数中最小的那个,\(c\)就称为\(a,b\)的最小公倍数,记作\([a,b]=c\)

\([4,6]=12\)

素因式分解找最小公倍数

对于最小公倍数,我们只需要选择素因子列表中指数比较大的那个就好了。

\[a=p_1^{a_1}\times p_1^{a_2} \times ... \times p_n^{a_n}\\ b=p_1^{b_1}\times p_1^{b_2} \times ... \times p_n^{b_n}\\ [a,b]=p_1^{max(a_1,b_1)}\times p_2^{max(a_2,b_2)}\times ... \times p_n^{max(a_n,b_n)} \]

举个例子

\[a=4,b=6\\ a=2^2,b=2^1\times 3^1\\ [a,b]=2^{max(2,1)}\times 3^{max(1,0)}=2^2\times 3^1=12 \]

最大公因数和最小公倍数之间的线性关系

\[ab=(a,b)\times [a,b] \]

使用素因数分解法不太适合计算机,辗转相除比较适合计算机,所以求解最小公倍数可以利用这个线性关系。

//lcm是最小公倍数 gcd是使用辗转相除法实现的最大公因数
function lcm(a,b)
	tmp = gcd(a,b)
	return a*b/tmp

最大公因数线性组合表示

最大公因数总可以以线性组合的方式表示

\[(a,b)=sa+tb \]

posted @ 2020-10-04 20:13  yudoge  阅读(955)  评论(0编辑  收藏  举报