\(\texttt{godmoo}\text{ }\texttt{の}\text{ }\texttt{數論學習筆記 之}\text{ }\boxed{因數與倍數}\)
定義
-
因數/約數,倍數:若 \(d \mid n\),則 \(d\) 是 \(n\) 的因數,\(n\) 是 \(d\) 的倍數。
-
公因數/公約數,公倍數:公共的因數/約數、倍數。
-
最大公因(約)數:\(GreatestCommonDivisor(gcd)\),最大的公因數,規定 \(gcd(0,a)=a\)。
-
最小公倍數:\(LeatestCommonMultiple(lcm)\),最小的公倍數。
\(eg.\text{ }gcd(24,18)=6,lcm(24,18)=72\)
性質
- 唯一分解定理:任意大於 \(1\) 的整數都可以寫成有限個質數乘積的形式,即:
\(n=\prod_{i=1}^m p_i^{c_i}\) - \(gcd\) 和 \(lcm\) 的最值表示法:若有 \(x=\prod_{i=1}^m p_i^{a_i}\),\(y=\prod_{i=1}^m p_i^{b_i}\),則有:
正確性:由定義推出。
- \(gcd\) 與 \(lcm\) 的性質:\(x \times y=gcd \times lcm\)
正確性:由 \(gcd\) 和 \(lcm\) 的最值表示法推出。
\(\bold{gcd}\) 求法
- 分解質因數:分解後用 \(gcd\) 的最值表示法,\(O(\sqrt{n})\)
- 歐幾里得演算法:又名輾轉相除法,\(gcd(a,b)=gcd(b,a\text{ }mod\text{ }b)\)
證明:
記 \(g=gcd(a,b)\)
\(\large\text{Part1.}\) 證明是公因數
首先 \(g\) 是 \(a\),\(b\) 的因數;
我們知道,\(a\text{ }mod\text{ }b=a-\lfloor\frac{a}{b}\rfloor b\) ;
那麼 \(g\) 也是這個式子的因數;
所以 \(g\) 是 \(b\) 和 \(a\text{ }mod \text{ }b\) 的公因數。
\(\large\text{Part2.}\) 證明是最大公因數
假設存在更大的公因數 \(k\);
則 \(k \mid b\) 且 \(k \mid a-\lfloor\frac{a}{b}\rfloor b\);
於是 \(k \mid b\) 且 \(k \mid a\);
此時,\(k\) 是 \(a\) 和 \(b\) 的公因數;
又 \(k \gt g\),與 \(g=gcd(a,b)\) 矛盾;
所以 \(g=gcd(b,a\text{ }mod\text{ }b)\)。
ll gcd(ll x,ll y){
if(!y) return x;
return gcd(y,x%y);
}
也可以寫成:
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
- 更相減損術:\(gcd(a,b)=gcd(b,a-b)\)
證明:與輾轉相除法的類似,不證。
- \(\bm{Stein}\) 演算法:
針對大資料時,取模運算的效能會很低,使得輾轉相除法的效率不佳;但更相減損術的效率又不高,每次只能減一此。於是,\(Stein\) 演算法橫空出世,它避免了取模運算,但實測下來,它在大資料下的表現略勝一籌。
思想:\(Stein\) 演算法基於更相減損術,由於計算機是以 \(2\) 進位制儲存的,所以位運算的效率極高,所以考慮用位移運算最佳化更相減損術。
流程:
\(Case\text{ }1:\) 當 \(a,b\) 一奇一偶時,
偶數除以 \(2\),顯然不影響結果;
\(Case\text{ }2:\) 當 \(a,b\) 都是偶數時,
答案為 \(2\text{ }gcd(\frac{a}{2},\frac{b}{2})\);
\(Case\text{ }3:\) 當 \(a,b\) 都是奇數時,
無法最佳化,直接做更相減損術;
\(【性質】:\text{ }\)\(Case\text{ }3\) 後必為 \(Case\text{ }1\),效率得到保證。
ll stein(ll x,ll y){
if(x<y) x^=y,y^=x,x^=y; // swap的黑科技
if(!y) return x;
if(!(x&1)&&!(y&1)) return stein(x>>1,y>>1)<<1;
if(!(x&1)&&(y&1)) return stein(x>>1,y);
if((x&1)&&!(y&1)) return stein(x,y>>1);
return stein(y,x-y);
}