扩展欧几里得自学笔记

洛谷上的板子 https://www.luogu.org/problem/P1082
就此题来分析:
数学转换,推导
也就是求ax≡1(modb)
转换一下:ax%b=1 ---》 ax+by=1
当然y只是个“雷锋”未知数,管它正负呢(但y为整数)最终求的是x
对于ax+by=1,我们用exgcd来求解。exgcd原来是求解ax+by=gcd(x,y)的解的。
这里要有解,那么a,b互质,gcd(a,b)=1
证明:gcd(a,b)为a和b的因子,那么ax+by为gcd(a,b)的倍数(x,y为整数),对于此题方程:ax+by=1,那么gcd(a,b)只能是1了,所以a,b互质
可以愉快的用exgcd了!(可惜还要推不少式子啊)
由已经得到的:gcd(a,b)=1(上面已证) gcd(a,b)=gcd(b,a%b)(普通的gcd)来做这题吧
已知原式:ax+by=gcd(a,b) 假设xx,yy为gcd(b,a%b)的答案
也就是bxx+(a%b)yy=gcd(b,a%b),而我们已知道gcd(a,b)=gcd(b,a%b),且gcd(a,b)=1
那么ax+by=1 bxx+(a%b)yy=1 ax+by=bxx+(a%b)yy
是不是感觉%有点别扭?其实就是它阻碍了一眼看出答案,处理:a%b=a-(int(a/b))(int在这里表示下取整,oier的习惯,不写int也行,但这里写出来减少误会)
方程也就成了 : ax+by=bxx+(a-int(a/b)b)yy
推一下:a
x+by=bxx+(a-int(a/b)b)yy ax+by=bxx+ayy-bint(a/b)yy ax+by=ayy+b(xx-yyint(a/b))
现在可以看出一组答案了吧,a
x=ayy by=(xx-yyint(a/b))
这题值得好好推一下,看看我的草稿吧(当然,是我自学后自己做的草稿)、
a b
gcd(a,b)=1
ax+by=1
ax+by=gcd(b,a%b)
b
xx+(a%b)yy=gcd(b,a%b)
b
xx+(a%b)yy=gcd(a,b)
b
xx+(a%b)yy=1
a
x+by=bxx+(a%b)yy
a
x+by=bxx+(a-bint(a/b))yy
ax+by=bxx+ayy-b(int(a/b))yy
ax+by=ayy+b(xx-int(a/b)yy)
x=yy y=(xx-int(a/b)
yy)
并不很全因为有些证名我看过了,没有再证
程序递归实现
递归实现应该很明显吧,至于边界条件吗还是有方程入手
ax+by=gcd(a,b) 当b=0是gcd(a,b)明显为gcd(a,0)=a,那么x等于1方程肯定成立
相信也能看出,此处y可为任意值,当然是理论上,建议直接让y=0,不然可能会出现数值过大而越界
至于最后的答案:要求是最小正整数,那么需要一些处理,因为求出的只是其中一个解
再假设一个雷锋未知数 c (整数)
代入方程:ax+by+abc-abc=1 a(x+bc)+b(y-ac)=1 显然x,y变成了(x+bc)和(y-ac),且x,y仍是整数
由此,得到此方程任意解(用上面是用x表示)减去b的倍数或加上b的倍数都是此方程解
那么若x为负数,不断加上b,如果为正数了,对b取模保证是最小正整数解
下面就是代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map> 
using namespace std;
#define re register int
#define int long long
inline int read(){
    int x=0,ff=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')ff=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*ff;
}
//萌新的推导过程,乱的一批
/*
a b
gcd(a,b)=1
ax+by=1
ax+by=gcd(b,a%b)
b*xx+(a%b)*yy=gcd(b,a%b)
b*xx+(a%b)*yy=gcd(a,b)
b*xx+(a%b)*yy=1
a*x+b*y=b*xx+(a%b)*yy
a*x+b*y=b*xx+(a-b*int(a/b))*yy
a*x+b*y=b*xx+a*yy-b*(int(a/b))*yy
a*x+b*y=a*yy+b*(xx-int(a/b)*yy)
x=yy y=(xx-int(a/b)*yy)
*/
int x,y,xx,yy;
void gcd(int a,int b){
    if(b==0){x=1;y=0;return;}
    gcd(b,a%b);
    xx=x;yy=y;
    x=yy;y=(xx-(a/b)*yy);
}
signed main(){
    int a,b;a=read();b=read();
    gcd(a,b);
    while(x<0)x+=b;
    x%=b;
    printf("%lld\n",x);
    return 0;
}

好了,对于此题就结束了

猜你喜欢

转载自www.cnblogs.com/ffrxy01bt/p/11261296.html