自己一直用gcd函数,原理都快不记得了,现在写这篇博客来复习一下。
比如找200和90的GCD最暴力的办法是一个for循环从2到89,找到最大的i使得200%i==0且90%i==0.
上面的办法在时间效率很慢,复杂度为O(n)。
下面讲一下辗转相除法的原理。还是200和90为例。
先贴个代码。

int GCD(int a,int b)
{
    if(a<b) swap(a,b);
    int i=a%b;//i为x除以y的余数。
    while(i!=0)
    {
        a=b;
        b=i;
        i=a%b;
    }
    return b;
}

第一步:令c=gcd(a,b),则设a=mc,b=nc
第二步:根据前提可知r =a-kb=mc-knc=(m-kn)c
第三步:根据第二步结果可知c也是r的因数
第四步:可以断定m-kn与n互质(假设m-kn=xd,n=yd (d>1),则m=kn+xd=kyd+xd=(ky+x)d,则a=mc=(ky+x)cd,b=nc=ycd,则a与b的一个公约数cd>c,故c非a与b的最大公约数,与前面结论矛盾),因此c也是b与r的最大公约数。
从而可知gcd(b,r)=c,继而gcd(a,b)=gcd(b,r)。
2.辗转相减法

int GCD(int a, int b)
{
    while(a!=b)
    {
        if (a > b) a -= b;
        else b -= a;
    }
    return a;
}

更相减损法:
两个数gcd(x,y)=gcd(x,y-x).
三个数gcd(x,y,z)=gcd(x,y-x,z-y)
多个数gcd(a1,a2,a2,.....,an)=gcd(a1,a2-a1,a3-a2,.....,an-an-1);
下面放一道模板提
一道GCD:
https://ac.nowcoder.com/acm/contest/10743/A

代码的注释部分是自己做错的地方。
//由gcd定义得两个数的最大公约数为其中较小的一个。
#include<iostream>
#include<bits/stdc++.h>
#define qc std::ios::sync_with_stdio(0);
using namespace std;
typedef long long ll;
typedef unsigned long long int ul;
typedef double dl;
int main()
{
    int n;
    int a[100005];
    int gcd;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    sort(a+1,a+1+n);
    gcd=0;//gcd初始化为0,不能为1,0和整数m的最大公约数都为m,1与m的数都为1.
    for(int i=2;i<=n;i++)
        gcd=__gcd(a[i]-a[i-1],gcd);//由gcd(x,y,z)=gcd(x,y-x,z-y),注意__中的一个参数是上一个求的gcd。
    cout<<gcd<<" "<<(gcd-a[1]%gcd)%gcd<<endl;//将a[1]变为不大于gcd的数。
}