扩展欧几里得算法
本文档基于 AcWing 制作
什么是欧几里得算法?
定义
欧几里得算法 ( g c d ) (gcd) (gcd),又叫辗转相除法,是指用于计算两个非负整数a,b的最大公约数。
证明: g c d ( a , b ) = g c d ( b , a m o d b ) gcd(a,b)=gcd(b,a \ mod \ b) gcd(a,b)=gcd(b,a mod b)
证明:
设 a ≤ b , a = b ∗ r + c , d = ( a , b ) a \leq b,a=b * r+c,d=(a,b) a≤b,a=b∗r+c,d=(a,b),则 c = a % b = a − b ∗ r c=a \% b=a-b*r c=a%b=a−b∗r
(1). g c d ( a , b ) < = g c d ( b , a m o d b ) gcd(a,b)<=gcd(b,a \ mod \ b) gcd(a,b)<=gcd(b,a mod b)
令 d ∣ a d|a d∣a, d ∣ b d|b d∣b, 则 d ∣ c d|c d∣c, 即 a , b a,b a,b的公约数同时也是 a , c a,c a,c的公约数,
a , b a,b a,b的最大公约数也是 a , c a,c a,c的公约数, g c d ( a , b ) ≤ g c d ( a , a m o d b ) gcd(a,b) \leq gcd(a,a \ mod \ b) gcd(a,b)≤gcd(a,a mod b)
(2). g c d ( b , a ) ≤ g c d ( b , a m o d b ) gcd(b,a) \leq gcd(b,a \ mod \ b) gcd(b,a)≤gcd(b,a mod b)
令 d ∣ b d|b d∣b, d ∣ c d|c d∣c,则 d ∣ a d|a d∣a ,即 b , c b,c b,c的公约数同时也是 a , b a,b a,b的公约数, b , c b,c b,c的最大公约数同时也是 a , b a,b a,b的公约数, g c d ( b , a m o d b ) ≤ g c d ( a , b ) gcd(b,a \ mod \ b) \leq gcd(a,b) gcd(b,a mod b)≤gcd(a,b)
(3).综上可得,gcd(a,b)=gcd(a,a mod b),证毕
代码----欧几里得算法
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
实例:
AcWing 872.最大公约数
原题链接:AcWing 872.最大公约数
题目描述
给定 n n n对正整数 a i a_i ai, b i b_i bi,请你求出每对数的最大公约数。
输出格式
第一行包含整数 n n n。
接下来 n n n行,每行包含一个整数对 a i , b i a_i,b_i ai,bi。
输出格式
输出共 n n n行,每行输出一个整数对的最大公约数。
数据范围
1 1 1 ≤ \leq ≤ n n n ≤ \leq ≤ 1 0 5 10^5 105
1 1 1 ≤ \leq ≤ a i , b i ≤ 2 × 1 0 9 a_i, b_i \leq 2 \times 10^9 ai,bi≤2×109
输入样例:
2
3 6
4 6
输出样例:
3
2
代码
- 时间复杂度为 O ( log n ) O(\log n) O(logn)
#include<bits/stdc++.h>
#define int long long
using namespace std;
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--)
{
int a,b;
cin>>a>>b;
cout<<gcd(a,b)<<'\n';
}
return 0;
}
扩展欧几里得算法
算法基础——裴蜀定理
定义:
定义:若 a , b a,b a,b是整数,且 g c d ( a , b ) = d gcd(a,b)=d gcd(a,b)=d,那么对于任意整数 x , y x,y x,y, a x + b y ax+by ax