我们会经常在各大评测网站看到类似于以上结果的问题如洛谷B3736,POJ319,都是此类问题,那么本着知道结论就不要现推的精神,本人在此对于gcd进行一个梳理,不敢说是权威,仅供参考啊!
那么我们首先给定两个数a,b求其最大公约数(下文全用gcd代替)
很明显,从特殊到一般,我们假定均为素数,那么gcd(a,b)=1
如果只有一个素数,那么gcd(a,b)=1
那如果不是素数呢?你是列竖式,还是短除法?
好!有耐心!
升级一下:求30792和3069的gcd?
很显然,此时去手算,很大概率会算错,即使算对,也定会耗费很长时间对吧,就不值当了,毕竟这不是数学社区。
前导知识
我们首先需要知道几个表示方法——对于%的运算法则:
1.(a+b)%c=(a%c+b%c)%c;
2.(a-b)%c=(a%c-b%c)%c;
3.(a*b)%c=(a%c*b%c)%c;
4.a^b%c=(a%c)^b%c
所以应该怎么做?
我们直接给出结论:
gcd(a,b)=gcd(b,a mod b)
也就是两个整数的最大公约数等于其中较小的数和两数相除余数的最大公约数
如何证明?
假设c = gcd(a,b),则存在m,n,使a = mc, b = nc;
令r = a mod b,即存在k,使r = a-kb = mc - knc = (m-kn)c;
故gcd(b,a mod b) = gcd(b,r) = gcd(nc,(m-kn)c) = gcd(n,m-kn)c;
则c为b与a mod b的公约数;
假设d = gcd(n,m-kn), 则存在x,y, 使n = xd, m-kn = yd; 故m = yd+kn = yd+kxd = (y+kx)d;
故有a = mc = (y+kx)dc, b = nc = xdc; 可得 gcd(a,b) = gcd((y+kx)dc,xdc) = dc;
由于gcd(a,b) = c, 故d = 1;
即gcd(n,m-kn) = 1, 故可得gcd(b,a mod b) = c;
故得证gcd(a,b) = gcd(b,a mod b).
———————————————————————————————————————————当然,万能的网上给了一个更简洁的做法,虽然我的是第二种,但是麻烦了好多
设计?
三目运算符
return b==0?a:gcd(b,a%b);
拓展欧几里得算法(exgcd)
给予二整数 a 与 b, 必存在有整数 x 与 y 使得ax + by = gcd(a,b)
裴蜀定理!
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int r=exgcd(b,a%b,x,y);
int temp=y;
y=x-(a/b)*y;
x=temp;
return r;
}
RSA算法
原理:根据数论,我们知道寻求两个大素数是很简单的,而将它们的乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。