数论——最大公因数
最大公因数
如果\(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
\]