算法 {最大公约数GCD}
最大公约数GCD
定義
#最大公約數/Greatest Common Divisor
/GCD#
若干個整數
A
i
Ai
Ai(不能全为0), 找到最大的整数
T
>
0
T>0
T>0 滿足:
∀
a
∈
A
i
,
a
%
T
=
0
\forall a \in Ai, a\%T =0
∀a∈Ai,a%T=0;
.
比如{-6,0,4}
的GCD為2
;
等價定義: 所有Ai
的約數集合的交集 中的最大值, 為GCD;
性質
#從質因數分解角度去看GCD;#
令a = p1^k1 * p2^k2 * p3^k3 * ...
, b = p1^kk1 * p2^kk2 * p3^kk3 * ...
, c = p1^kkk1 * p2^kkk2 * p3^kkk3 * ...
;
那麼 p1^min(k1,kk1,kkk1) * p2^min(k2,kk2,kkk2) * p3^min(k3,kk3,kkk3) * ...
就是a,b,c
的GCD;
@DELI;
#GCD的除法#
已知GCD(a,b) == c
; 對於c
的任意的約數d
, 則有GCD(a/d, b/d) == c/d
;
.
證明: 可以藉助上一條性質, 令d = p1^K1 * p2^K2 * ...
, 那麼因為k1/kk1/kkk1 >= K1
, 整除除法 在質因數分解的角度 就是做指數的減法, 即c/d
等於 讓c
的各個指數減去K1,K2,...
, 又因為min(k1-K1, kk1-K1, kkk1-K1) == min(k1,kk1,kkk1)-K1
;
算法
若干个數的GCD (质因数分解)
代码
GCD( vector< map<int,int> > _v){ // `v`为所有数的质因数分解;
map<int,int> ANS; // 答案的质因数分解
for( p : 同时出现在`v[0|1|...]`里的质因子){
ANS[p] = min( {v[0|1|...][p]}); // 取最小*幂次方*;
}
return ANS;
}
性质
从质因数分解的角度 (就和二进制运算时的拆位一样), 单独研究某一个质因子p, 取最小幂次方m
, 那么他在答案里 就是p^m
;
若干个數的GCD ( l o g N logN logN取模)
代码
template< class _Type_> _Type_ ___GCD( _Type_ const* _arr, int _len){ // 返回值一定`>0`;
ASSERT_SYSTEM_( _len > 0);
auto gcd = []( _Type_ _a, _Type_ _b){ ASSERT_SYSTEM_( (_a==0 && _b==0)==0); while( _b != 0){ _a %= _b; {auto t=_a; _a=_b; _b=t;}} return (_a<0 ? (-_a):_a);};
_Type_ ANS = _arr[0];
for( int i = 1; i < _len; ++i){ ANS = gcd( ANS, _arr[i]);}
return ANS;
} // ___GCD
性質
樸素的GCD算法 是直接返回_a
, 而不是abs(_a)
這是我們自己的規定;
這很重要 比如在拓展GCD算法裡, 當if( b == 0)
時, 此時GCD是abs(a)
, 因此如果你直接返回{1,0}
這是錯誤的, 比如a=-2
, 顯然-2 * 1 != 2
, 因此要特判;
求GCD==?
的數對個數
求
N
×
N
N \times N
N×N裡 GCD==質數
的數對個數
@LINK: (https://editor.csdn.net/md/?not_checkout=1&articleId=126848932)-(@LOC_1)
;
求
A
×
B
A\times B
A×B裡 GCD==x
的數對個數
@LINK: https://editor.csdn.net/md/?not_checkout=1&articleId=130248080
;
求
[
L
1
,
R
1
]
×
[
L
2
,
R
2
]
[L1,R1] \times [L2,R2]
[L1,R1]×[L2,R2]裡 GCD==x
的數對個數
模板題: @LINK: https://www.acwing.com/problem/content/2704/
;
利用二維前綴和的思想, 令F(A,B): A*B裡 GCD==x的數對個數
(這是個算法模板), 那麼答案為F(R1, R2) - F(L1-1, R2) - F(L2, R1-1) - F(L1-1, L2-1)
;
例题
https://editor.csdn.net/md/?not_checkout=1&articleId=130320865
筆記
对两数AB的GCD, (规定两者都是自然数, 且不同时为 0 0 0)
假设AB的所有公约数集合是S, 做法是: 找到另外两个数CD, 其公约数集合也等于S;
… 公约数集合相同, 自然最大公约数也相同;
令A >= B, A = Ka * G, B = Kb * G (G为AB的GCD, Ka与Kb互质)
令C = A % B, 即: C = (Ka % Kb) * G
根据: 取模数, 可知: C与Kb一定互质, 但与Ka不一定互质;
即, (A, B的GCD)为G, 而(B, C的GCD)也为G;
故求(A, B)的GCD, 且A>=B, 等价于求(B, A%B)的GCD
因为要保证第一参数>=第二参数, 所以要写成(B, A%B), 而不是(A%B, B)
比如, 求(10, 6)的GCD
(10, 6) -> (6, 4) -> (4, 2) -> (2, 0)
每次取模, 相当于取半, 所以时间是Log2(N);
递归的终结是: 第二参数为0
@DELI;
Property-1
x
x
x 的约数个数
A = p 1 a 1 ∗ p 2 a 2 ∗ . . . A = p_1^{a_1} * p_2^{a_2} * ... A=p1a1∗p2a2∗..., then the number of divisors of A A A equals ( 1 + a 1 ) ∗ ( 1 + a 2 ) ∗ . . . (1 + a_1) * (1 + a_2) * ... (1+a1)∗(1+a2)∗...;
Proof:
.
For any divisor
a
a
a of
A
A
A, every Prime-Factor of
a
a
a must be also a Prime-Factor of
A
A
A;
.
Therefore, for every item
p
i
a
i
p_i^{a_i}
piai, there are
a
1
+
1
a_1 + 1
a1+1 choices:
p
i
0
,
p
i
1
,
p
i
2
,
.
.
.
p_i^0, p_i^1, p_i^2, ...
pi0,pi1,pi2,...;
@Delimter;
Property-2
a
∈
i
n
t
a \in int
a∈int 的最大约数个数
The Maximal-Divisor-Count in the range int
[
1
,
2147483647
]
[1, 2147483647]
[1,2147483647] is
1536
1536
1536;
.
Two numbers
a
=
1745944200
/
2113511400
a = 1745944200/2113511400
a=1745944200/2113511400 attains this peak:
2
3
∗
3
3
∗
5
2
∗
7
∗
11
∗
13
∗
17
∗
(
19
/
23
)
2^3 * 3^3 * 5^2 * 7 * 11 * 13 * 17 * (19/23)
23∗33∗52∗7∗11∗13∗17∗(19/23);