扩展欧几里得
根据我国的某搜索网站,对扩欧的定义如下“ 扩展欧几里德算法是用来在已知a, b求解一组x,y,使它们满足贝祖等式: ax+by = gcd(a, b) =dax+by=gcd(a,b)=d (解一定存在,根据数论中的相关定理 )。”
说人话
简而言之,扩欧就是大佬的凑数(或者叫不定方程???)
首先 我们写一组一看就解不出来的方程 ax+by=cax+by=c
a,b,c,x,y\in za,b,c,x,y∈z
扩欧就是证明这组方程的解的情况
我们考虑 x=k_1gcd(x,y),y=k_2gcd(x,y)x=k
1
gcd(x,y),y=k
2
gcd(x,y)
所以原式可以看成 (k1a+k2b)gcd(x,y)=c(k1a+k2b)gcd(x,y)=c
所以 cc 一定是 gcd(x,y)gcd(x,y) 的倍数
我们考虑辗转相除的过程,从辗转相除的后一项推出前一项。
gcd(a,b)==gcd(b,a%b)gcd(a,b)==gcd(b,a%b)
所以凑出构造方程 bx1+(a%b)y2=gcd(b,a%b)bx1+(a%b)y2=gcd(b,a%b) --后一项的方程
所以, bx1+(a%b)y2=ax+bybx1+(a%b)y2=ax+by
然后又因为 a%b=a-(a/b)a%b=a−(a/b) 的取整*b(取整笔者下文暂时用<[]>代替)
所以 bx1+[a-<a/b>*b]y2=ax+bybx1+[a−<a/b>∗b]y2=ax+by
展开后得 ay2+<x1-[a/b]y2>b=ax+byay2+<x1−[a/b]y2>b=ax+by
笔者当初看到这就懵了。这怎么做啊
事实证明,凑数的力量是伟大的
你“令” x=y2,y=x1-<[a/b]>y2x=y2,y=x1−<[a/b]>y2 不就是原方程的一个解吗?
这就构成了一个递归的过程,递归出口就在当x=1且y=0时。
即 gcd(a,b)1+0b=gcd(a,b)gcd(a,b)∗1+0∗b=gcd(a,b) (因为辗转相减,所以a==gcd(a,b)了)
扩欧模板,
因为这道题可以看做ax-bk=1
所以就妥妥地上了扩欧
#include<bits/stdc++.h>
using namespace std;
int x,y,k;
void exgcd(int a,int b){
if(b==0){
x=1;
y=0;
return ;
}
exgcd(b,a%b);
k=x;
x=y;
y=k-a/b*y;
}
int a,b;
int main(){
cin>>a>>b;
exgcd(a,b);
cout<<(x+b)%b;
return 0;
}