辗转相除法(欧几里得算法)的证明以及代码
模板题:最大公约数
给定 n 对正整数ai,bi,请你求出每对数的最大公约数。
输入格式
第一行包含整数n。
接下来 n 行,每行包含一个整数对 ai,bi。
输出格式
输出共 n 行,每行输出一个整数对的最大公约数。
数据范围
1≤n≤10^5,
1≤ai,bi≤2×10^9
输入样例:
2
3 6
4 6
输出样例:
3
2
AC代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int INF = 1e9;
const int N = 1e5 + 5;
int n;
int gcd(int a, int b){
if(b == 0)return a;
return gcd(b,a%b);
//简写:return b ? gcd(b,a%b):a;
}
int main()
{
cin>>n;
while(n--){
int a,b;
cin>>a>>b;
cout<<gcd(a,b)<<endl;
}
return 0;
}
思路分析:
先讲几个基本概念:
约数:约数,又称因数。整数a除以整数b(b≠0) 除得的商正好是整数而没有余数,我们就说a能被b整除,或b能整除a。a称为b的倍数,b称为a的约数。
公约数: 顾名思义,多个数公共的约数,我们通常把符号(a,b)表示为a和b的公约数。
符号|: '|'为整除符号,对于整数a,b(a≠0),若存在整数k,使b = ka, 则称a整除b,或b能被a整除,记为a∣b。
辗转相除法(欧几里得算法)
核心代码: gcd(a , b)== gcd ( b , a % b)
证明:
易证:a % b = a -( a / b)× b = a - c × b
d|a, d|b 得 d|xa+yb
若d是(a,b)的公约数,则知d|a且d|b,则易知d|a-c×b,所以d也是(b,a%b)公约数(根据d|a,d|b,所以d|xa+yb)
若d是(b,a%b)的公约数 则知 d|b 且 d|a-kb 则 d|a-k * b+kb = d|a 故而d|b 故而 d也是(a,b)的公约数
(公式:显然,若d|a 且d|b ,则有 d|k1∗a+k2∗b,故当 d|a−k∗b 且 d|b 则 d|a−k∗b+k∗b)
因此(a,b)的公约数集合和(b,a%b)的公约数集合相同 所以他们的最大公约数也相同。
当a%b==0时,因为任何数都可以整除0,因此gcd(a,0)=a;
借鉴文章: https://www.acwing.com/solution/content/10534/