历史上第一个称得上算法的好像就是这个欧几里得算法,其实就是地球人都知道的辗转相除,故又叫“辗转相除法”不要小看她,她是很美的。
 
  简单的描述就是,记gcd(a,b)表示非负整数a,b的最大公因数,那么:gcd(a,b) = gcd(b,a%b)
Euclid算法定义:
gcd(a,b)=gcd(b, a+kb) a,b,k为任意整数,即gcd(a,b)=gcd(b, a mod b) a≥0,b>0
 
  • Example:gcd(55,22)=gcd(22, 55mod22)=gcd(22,11)=11 
 
  证明:假定d=gcd(a,b),那么有d|a和d|b.对任何正整数b,a,可表示为如下形式: a=kb+r ≡r mod b, a mod b =r , 因此,有(a mod b )= a-kb,k为某个整数。但由于d|b,b也能整除kb, 而d|a,故有d|(a mod b), 这表明d 也是b 和(a mod b) 的公因子。由于这是可逆的,如果d 是b 和(a mod b) 的公因子,那么d|kb,且d|[kb+(a mod b)],这等同于d|a。这样a和b的公因子集合等同于b 和(a mod b) 的公因子集合。
Euclid算法的应用:
求两个数的最大公约数gcd(55,22)=gcd(22, 55mod22)=gcd(22,11)=11 
 
  最常用的就是在RSA里边求密钥
 
  RSA算法,是非对称加密的标准算法,其实算法很简单:
 
  找到两个素数p,q,再找一个数r,使gcd(r,(p-1)(q-1))=1,也就是说互素,然后再找一个数m,使rm=1(mod (p-1)(q-1)),然后再作乘法n=pq,然后把pq丢掉,最好是让任何人都不知道,包括自己(免得说梦话的时候被人听到),然后手里拿到r,m,n,r就是Private Key,只有你知道,而m,n就是Public Key。设信息为a,加密过程:a^r=b (mod n),b就是密文,解密过程:b^m=a(mod n),反过来用m加密,用r解密是一样的。
 Euclid算法在RSA密码体系中的实现
  #include<iostream.h>
 
  #include<math.h>
 
  #include <windows.h>
 
  int mul(int x,int r,int n);//大树幂乘
 
  int niyuan(int n,int u); //求逆元
 
  int gcd(int a,int b);//求最大公约数
 
  bool IsPrime(int a );//判断是否为素数
 
  void main()
 
  {
 
  system("color 3f");
 
  system("title ☆★ RSA公钥密码 ★☆");
 
  cout<<"\t\t****RSA公钥密码加密解密系统****"<<endl;
 
  int p ,q ;
 
  cout<<" 请输入两个素数 :p , q :"<<endl;
 
  cin>>p>>q;
 
  int n=p*q;
 
  int w=(p-1)*(q-1);
 
  int e;
 
  cout<<"请输入加密密钥 e (与"<<w<<"最大公约数为 1 )"<<endl;
 
  cin>>e;
 
  int d;
 
  d=niyuan(w,e);
 
  cout<<"经计算解密得到密钥 :"<<d<<endl;
 
  cout<<"输入需要加密的明文:"<<endl;
 
  int ming;
 
  cin>>ming;
 
  cout<<"经加密后得到的密文:"<<mul(ming,e,n)<<endl;
 
  cout<<"退出系统请按 1 "<<endl;
 
  cout<<"进行解密请按 2 "<<endl;
 
  int k;
 
  cin>>k;
 
  if(k==2)
 
  {
 
  cout<<"请输入需解密的密文:"<<endl;
 
  int miwen;
 
  cin>>miwen;
 
  cout<<"经解密后得到的明文:"<<mul(miwen,d,n)<<endl;
 
  }
 
  }
 
  int mul(int x,int r,int n)//大树幂乘函数
 
  {
 
  int a=x;
 
  int b=r;
 
  int c=1;
 
  while(b!=0)
 
  {
 
  if(b%2!=0)
 
  {
 
  b=b-1;
 
  c=(c*a)%n;
 
  }
 
  else
 
  {
 
  b=b/2;
 
  a=(a*a)%n;
 
  }
 
  }
 
  return c ;
 
  }
 
  int niyuan(int n,int u)//求逆元
 
  {
 
  int n1=n;
 
  int n2=u;
 
  int b1=0;
 
  int b2=1;
 
  int q=n1/n2;
 
  int r=n1-q*n2;
 
  while(r!=0)
 
  {
 
  n1=n2;
 
  n2=r;
 
  int t=b2;
 
  b2=b1-q*b2;
 
  b1=t;
 
  q=n1/n2;
 
  r=n1-q*n2;
 
  }
 
  if(n2!=1)
 
  {
 
  return 0 ;
 
  }
 
  else
 
  {
 
  return (b2+n)%n;
 
  }
 
  }
 
  int gcd(int a,int b)//求最大公约数
 
  {
 
  int n1=a;
 
  int n2=b;
 
  int q=n1/n2;
 
  int r=n1-q*n2;
 
  while(r!=0)
 
  {
 
  n1=n2;
 
  n2=r;
 
  q=n1/n2;
 
  r=n1-q*n2;
 
  }
 
  return n2 ;
 
  }
 
  bool IsPrime(int a)//判断是否为素数
 
  {
 
  int b=(int)sqrt(a);
 
  int temp;
 
  for(int i=2;i<=b;i++)
 
  {
 
  temp=a%i;
 
  }
 
  if(temp==0)
 
  {
 
  return false ;
 
  }
 
  else
 
  {
 
  return true ;
 
  }
 
  }
shell 中求最大公约数:
 
#!/bin/bash
# gcd.sh: greatest common divisor
#         Uses Euclid's algorithm
#  The "greatest common divisor" (gcd) of two integers
#+ is the largest integer that will divide both, leaving no remainder.
#  Euclid's algorithm uses successive division.
#  In each pass,
#+ dividend &lt;---  divisor
#+ divisor  &lt;---  remainder
#+ until remainder = 0.
#+ The gcd = dividend, on the final pass.
## ------------------------------------------------------
# Argument check
ARGS=2
E_BADARGS=65
if [ $# -ne "$ARGS" ]
then
  echo "Usage: `basename $0` first-number second-number"
  exit $E_BADARGS
fi
# ------------------------------------------------------

gcd ()
{
  dividend=$1                    #  Arbitrary assignment.
  divisor=$2                     #+ It doesn't matter which of the two is larger.
                                 #  Why not?
  remainder=1                    #  If uninitialized variable used in loop,
                                 #+ it results in an error message
                                 #+ on the first pass through loop.
  until [ "$remainder" -eq 0 ]
  do
    let "remainder = $dividend % $divisor"
    dividend=$divisor            # Now repeat with 2 smallest numbers.
    divisor=$remainder
  done                           # Euclid's algorithm
}                                # Last $dividend is the gcd.
 
gcd $1 $2
echo; echo "GCD of $1 and $2 = $dividend"; echo

# Exercise :
# --------
#  Check command-line arguments to make sure they are integers,
#+ and exit the script with an appropriate error message if not.
exit 0
 
---------------------相关链接--------------------