GCD && ExtendGCD
计算最大公约数和不定方程
•GCD相关性质
性质1.$GCD(a,b)=GCD(-a,b)=GCD(a,-b)=GCD(\left | a \right |,\left | b \right |)$;
性质2.$GCD(a,b) = GCD(a,a-b) = GCD(b,a-b)$;
性质2推广.$GCD(a,b,c) = GCD(a,b-a,c-b) => GCD(a_1,a_2,...,a_n) = GCD(a_1,a_2-a_1,...,a_n-a_{n-1})$;
性质3.$GCD(a,b) = GCD(b,a\%b)$;
性质4.$GCD(fib_a,fib_b) = fib_{GCD(a,b)}$;($fib_i$: 斐波那契数列的第 i 项)
性质5.$GCD(a,b)\cdot LCM(a,b) = a\times b$;
性质6.设 $GCD(m,a) = 1$,则有 $GCD(m,ab) = GCD(m,b)$;
这就是说 “求 m 与另一个数的最大公约数时,可以把另一个数中与 m 互素的因数去掉”
性质7.设 $GCD(m,a) = 1$,那么若 m | ab,则 m | b;
这就是说 “若一个数被 m 整除,则把这个数中与 m 互素的因数去掉后仍被 m 整除”。
•与GCD相关的习题
[1]:CodeForces1152C , (my solution)
[2]:POJ2773
•不定方程
Bezout定理.如果 a,b 都是整数,则 ∃x,y 使得 ax+by = GCD(a,b);
Bezout定理推广.如果 a,b 都是整数,且 GCD(a,b) | c,则 ∃x,y 使得 ax+by = c;
•利用拓展欧几里得算法求解不定方程
$\begin{aligned} ax_1+by_1 &= GCD(a,b) \\ &= GCD(b,a\%b) \\ &=bx_2+a\%b\cdot y_2 \\ &= bx_2+(a-\lfloor \frac{a}{b} \rfloor \cdot b)y_2 \\ &=ay_2+b(x_2-\lfloor \frac{a}{b} \rfloor \cdot y_2)\end{aligned}$
由此可知,x1,y1 基于 x2,y2;
一直执行欧几里得算法来到最后一步 $GCD(a_i,0) = a_i$;
即 $a_i x_i+0=a_i$
所以,此时,满足此式的一个解为 xi=1,yi=0;
然后,根据上述推导的式子,向前回溯,依次求出 (xi-1,yi-1),(xi-2,yi-2),...,(x1,y1);
•extendGCD求解ax+by=GCD(a,b)代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define GCD(a,b) __gcd(a,b) 4 #define ll long long 5 6 ///求解满足 ax+by=GCD(a,b) 的一组整数解(x,y) 7 void extGCD(ll a,ll b,ll &x,ll &y) 8 { 9 if(b == 0) 10 { 11 x=1; 12 y=0; 13 return ; 14 } 15 16 extGCD(b,a%b,y,x); 17 y -= (a/b)*x; 18 } 19 20 int main() 21 { 22 ll a,b; 23 while(cin>>a>>b) 24 { 25 ll x,y; 26 extGCD(a,b,x,y); 27 28 printf("满足%lldx+%lldy=%lld的一组整数解为(%lld,%lld)\n",a,b,GCD(a,b),x,y); 29 } 30 }
•extendGCD求解ax+by=c代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define GCD(a,b) __gcd(a,b) 4 #define ll long long 5 6 ///求解满足 ax+by=c 的一组整数解(x,y) 7 void extGCD(ll a,ll b,ll &x,ll &y,ll c) 8 { 9 if(b == 0) 10 { 11 ///因为x=1求解的是ax+by=GCD(a,b)的解 12 ///所以要求解 ax+by=c 的解,只需在之前的基础上让x,y分别乘以c/GCD(a,b)即可 13 ///x=1*(c/a)=c/a 14 ///y=0*(c/a)=0 15 x=c/a; 16 y=0; 17 return ; 18 } 19 20 extGCD(b,a%b,y,x,c); 21 y -= (a/b)*x; 22 } 23 24 int main() 25 { 26 ll a,b,c; 27 while(cin>>a>>b>>c) 28 { 29 if(c%GCD(a,b) != 0) 30 { 31 puts("无解"); 32 continue; 33 } 34 35 ll x,y; 36 extGCD(a,b,x,y,c); 37 38 printf("满足%lldx+%lldy=%lld的一组整数解为(%lld,%lld)\n",a,b,c,x,y); 39 } 40 }
•ax+by=GCD(a,b)的所有整数解(x,y)的求法
通过拓展欧几里得求出 ax+by=GCD(a,b) 的一组解(x,y);
那么,其所有解为:
$\begin{aligned} &X=x+k\cdot \frac{b}{GCD(a,b)} \\ & Y=y-k\cdot \frac{a}{GCD(a,b)}\end{aligned}$
其中 $k\in Z$;
•与extendGCD相关的习题
[1]:CodeForces1055C
[2]:CodeForces548C
$GCD(fib_a,fib_b) = fib_{GCD(a,b)}$