最大公约数及应用
目录
- 最大公约数
- 最小公倍数
- 扩展欧几里得算法
- 求解线性同余方程
前置知识整除及同余
最大公约数GCD
最大公约数 意思为,两个及更多整数的最大的共同约数
(我们称\(GCD(x,y)\)为\(x,y\)的最大公约数)
当\(GCD(x,y)==1\)时我们称\((x,y)\)互质
辗转相除法
辗转相除法求两个数的最大公约数,又称欧几里得算法
出处:欧几里得《几何原本》
原理:\(GCD(x,y)==GCD(y,x \mod y )\)
-
证明
\(不妨设\)x>y$ ,则x一定可以被表示成\(x=n*y+r(0<=r<y)(n为整数)\)当\(r=0\)时 则\(y=gcd(x,y)\)
当\(r≠0\)时 设\(x=s*d,y=t*d(d为x,y的任一公约数)\)所以\(s,t为整数\)
则\(r=s*d-n*t*d=d*(s-n*t)\),而\(r=x\mod y\)
又因为\(s,t\)为整数,所以\(s-n*t\)为整数,所以\(d=r/(s-n*t)\),即d为r的因数
那么此时d即为\(x,y,r(x \mod y)\)三者的约数
所以\(x与y\)的最大公约数即为\(y与r(x \mod y)\)的公约数
(也可以称\(x\)与\(y\)的最大公约数在\((x,y)\)的公约数集合和\((y,x \mod y)\)的交集中)
在有限次重复上述过程后,最终会的到\(r=0\),此时的\(y\)即为最大公约数
** 证毕**
更相减损术
出处:可半者半之,不可半者,副置分母、子之数,以少减多,更相减损,求其等也。以等数约之 ------《九章算术》
原理 :\(gcd(x,y)=gcd(y,x-y)\) \(gcd(2x,2y)=2*gcd(x,y)\)
(这种方法个人看来可以用来求高精度的最大公约数,因为取模不好求高精度,但可以用高精度减法)
-
证明
设\(d\)为\(x\),\(y\)的任一公约数 则\(d|x,d|y\) 所以 \(d|(x-y)\)所以\(d既为(x,y)的公约数集合中的任一数,也为(y,x-y)的公约数集合中的任一数,所以两者集合相等\)
证毕 -
code
int gcd(int x,int y){
return y==0?x:gcd(y,x%y);
}
int gcd(int x,int y){
int d;
while(y!=0){
d=x%y;
x=y;
y=d;
}return x;
}
最小公倍数LCM
定理:\(a,b\)两个数的最大公约数乘以他们的最小公倍数就等于a和b本身的乘积
即:\(LCM(a,b)=a*b\) \(div\) \(GCD(a,b)\)
- 证明
设\(d=gcd(a,b)\)则\(m=a/d,n=b/d\),\(n,m\)互质(因为如果m,n不互质,那么最大公约数还能更大)
所以\(lcm(m,n)=m*n\)(因为\(gcd(m,n)=1\),所以m,n没有其他公因数,而最小公倍数一定为两数乘积,所以\(lcm(m,n)=m*n\))
所以\(lcm(a,b)=lcm(m*d,n*d)=d*lcm(m,n)=d*m*n=a*b\) \(div\) \(d\)
(因为a和b的因数中一定有d,所以最小公倍数的因数一定有d)
则\(lcm(a,b)=a*b\) div \(gcd(a,b)\)
证毕
附练习题
求最大公约数和最小公倍数
P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题
扩展欧几里德算法
扩展欧几里德算法是用来在已知\((a,b)\)时,求解一组\((p,q)\)使得
\(p*a+q*b=gcd(a,b)\)
(解一定存在)
- 证明
设\(d=gcd(a,b)\)
所以\(d|p*a,d|q*b\)
则\(d|(p*a+q*b)\)即\(d|d\)
显然\(d|d\)成立
所以原式成立
证毕
因为\(gcd(a,b)=gcd(b,a \mod b)\)
所以\(p*a+q*b=gcd(b,a \mod b)=p*b+q*(a-a/b*b)=q*a+(p-a/b*q)*b\)
即可将\(a\)与\(b\)的线性组合化简为\(b\)与\(a \mod b\)的线性组合
这样反复转换之后
当\(b=0\)时 \(gcd(a,b)=a\) 此时\(p=1,q=0\),递归返回即可
*code
int extended_gcd(int a,int b,int &p,int &q){
int ret;temp;
if(!b){
x=1;y=0;
return a;
}
ret=extended_gcd(b,a%b,p,q);
temp=p;
p=q;
q=temp-a/b*q;
return ret;
}
线性同余方程
定理1:对于\(a*x+b*y=c\) 该方程\(a*x==c(\mod b)\) 有整数解的充分必要条件
\(c\mod gcd(a,b)=0\) (裴蜀定理)
- 证明裴蜀定理
设\(d=gcd(a,b)\)
所以\(d|a*x,d|b*y\)
则\(d|(a*x+b*y)\)即\(d|c\)
所以原式充要条件为 \(c \mod gcd(a,b)=0\)即裴蜀定理
证毕
根据定理1 对于方程\(a*x+b*y=c\),我们可以用扩展欧几里德算出一组解\((x_0,y_0)\)
也就得到\(a*x_0+b*y_0=gcd(a,b)\) 两边同除以\(gcd(a,b)\)再乘\(c\)
则易得\(a*x_0*\frac{c}{gcd(a,b)}+b*y_0*\frac{c}{gcd(a,b)}=c\)
定理2:若\(gcd(a,b)=1\)且\(x_1,y_1\)为\(a*x+b*y=gcd(a,b)\)的一组解
\(x_1=\frac{x_0c}{gcd(a,b)},y_1=\frac{y_0c}{gcd(a,b)}\)
则该方程任一解\(x=x_1+b*t,y=y_1-a*t\),对\(\forall t \in Z\)都成立
根据定理2 可以求出方程所有解,实际问题一般求最小整数解
\(t=\frac{b}{gcd(a,b)},x=(x\mod t +t)\mod t\)
- code
int exgcd(int a,int b,int &x,int &y){
if(!b){
x=1;y=0;return a;
}
int temp,ret=exgcd(b,a%b,x,y);
temp=x;
x=y;
y=temp-(a/b)*y;
return ret;
}
bool check(int a,int b,int c,int &x,int &y){
int d=exgcd(a,b,x,y);
if(c%d) return 0;
int k=c/d;
x*=k;
y*=k;
return 1;
}
[模板]二元一次不定方程 (exgcd)
以这道题为例,详细分析最小值和最大值
先用扩展欧几里德算法,求出使\(ax+by=GCD(x,y)\)时\(x_0,y_0\)的值
两边同乘以c,则使\(ax+by=c\)时的值\(x_1=x_0*c/GCD(x,y),y_1=y_0*c/GCD(x,y)\)
\(ax+by=c \leftrightarrow a(x+m)+b(y+n)=c \leftrightarrow ax+by+am+bn=c (当且仅当am+bn=0时成立)\)
令\(m=\frac{t*b}{gcd(a,b)},n=-\frac{t*a}{gcd(a,b)}\)(t为任意整数),则\(am+bn=0\)成立
则通解\(x=x_1+\frac{t*b}{gcd(a,b)},y=y_1-\frac{t*a}{gcd(a,b)}\)(易得x随t的增大而增大,y随t的增大而减小)
又因为x为正整数
则\(x>=1\) 所以\(\lceil{\frac{(-x_1+1)gcd(a,b)}{b}}\rceil<=t\)
同理\(y>=1\) 所以\(\lfloor{\frac{(y_1-1)gcd(a,b)}{a}}\rfloor>=t\)
整理得 \(\lceil{\frac{(-x_1+1)gcd(a,b)}{b}}\rceil<=t<=\lfloor{\frac{(y_1-1)gcd(a,b)}{a}}\rfloor\)
(上下取整是因为t是整数)
所以t取最小值时,x取最小值,y取最大值
t取最大值时,x取最大值,y取最小值
如果\(\lceil{\frac{(-x_1+1)gcd(a,b)}{b}}\rceil>\lfloor{\frac{(y_1-1)gcd(a,b)}{a}}\rfloor\)
则不存在合法解使x,y为正整数
否则
存在合法解
关于解的个数,\(\lfloor{\frac{(y_1-1)gcd(a,b)}{a}}\rfloor-\lceil{\frac{(-x_1+1)gcd(a,b)}{b}}\rceil\)
需要注意的地方
用ceil和floor的时候记得是\(-x_1+1.0/m\),\(y_1-1.0/n\),(主要是精度的问题)
\(maxt-mint+1\)为解的个数(区间内数的个数)
参考文献
信息学奥赛之数学一本通
在此 鸣谢作者
感谢@kkksc0100,百忙中回答蒟蒻的问题