辗转相除法又称为欧几里得算法,用于计算两个非负整数a和b的最大公约数(Greatest Common Divisor),简写为gcd,其计算的公式为gcd(a,b)=gcd(b,a%b)。
辗转相除法正确性证明如下(参考百度百科):
证法1:
证明gcd(a,b)=gcd(b,a%b),不妨假设a>b,且r=a%b,且r!=0
设a=kb+r(a,k,b,r都为正整数且r!=0)
假设d是a和b的一个公约数,记作d|a,d|b,即a和b都可以被d整除
而r=a-kb,两边同时除以d有r/d=a/d-kb/d,因为d是a和b的一个公约数所以右式为整数,因此d/r也是整数,则d为r的一个公约数
因此d也是a%b的公约数(因为r是a%b)
因(a,b)和(b,a%b)公约数相等,所以最大公约数相等,所以原式得证。
证法2:(比1好理解,但是过程较长)
假设c=gcd(a,b),则存在m,n使得a=mc,b=nc;
令r=a%b,即存在k,使得r=a-kb=mc-knc;
故gcd(b,a%b)=gcd(b,r)=gcd(nc,mc-knc)=gcd(n,m-kn)*c;
则c为b和a%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%b)=c;
故得证gcd(a,b)=gcd(b,a%b);
代码如下
int gcd(int a,int b)
{
return a%b==0?b:gcd(b,a%b);
}
例题
UVA11417GCD
给定n,求
输入输出样例
输入 #1
10 100 500 0
输出 #1
67 13015 442011
import java.util.Scanner;
/**
* @author Zzy
* @create 2021-05-31 21:04
*/
public class Main {
public static int gcd(int a,int b){
return a%b==0?b:gcd(b,a%b);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(true){
int n =scanner.nextInt();
if(n==0)break;
int sum = 0;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
sum+=gcd(i,j);
}
}
System.out.println(sum);
}
}
}