贝祖定理:
即如果a、b是整数,那么一定存在整数x、y使得ax+by=gcd(a,b)。
换句话说,如果ax+by=m有解,那么m一定是gcd(a,b)的若干倍。(可以来判断一个这样的式子有没有解)
有一个直接的应用就是 如果ax+by=1有解,那么gcd(a,b)=1;

    int gcd(int a,int b){return b==0?a:gcd(b,a%b);}

然而这并不能告诉我们x,y解是多少。

扩欧

首先我们观察上面的式子发现一定有一个解a*1+b*0=gcd(a,b)。(b%a=0)

但是这个ab并不是我们想要的。不过我们可以倒推,原式即:

b*x1+(a%b)*y1=gcd

我们知道:a%b=a-(a/b)*b;带入:

b*x1 + (a-(a/b)*b)*y1

= b*x1 + a*y1 – (a/b)*b*y1

= a*y1 + b*(x1 – a/b*y1) = gcd

发现 x = y1 , y = x1 – a/b*y1

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
ll exgcd(ll a,ll b,ll &x,ll &y)//这个是返回值版的
{
if(!b)
{
x=1;y=0;
return a; //边界
}
int r=exgcd(b,a%b,x,y);
int temp=y; //把x y变成上一层的
y=x-(a/b)*y;
x=temp; //更改x和y的值,因为是引用的
return r; //得到a b的最大公因数
}
void exgcd1(ll a,ll b,ll &d,ll &x,ll &y)//这个不返回直接更新
{
if(!b)d=a,x=1,y=0;
else
{
exgcd1(b,a%b,d,y,x);
y-=x*(a/b);
}
}
int main()
{
ll a,b,d,x,y;
cin>>a>>b;
d=exgcd(a,b,x,y);//最大公约数
// exgcd1(a,b,d,x,y);
printf("%d %d",x,y);//x,y已经被更新了
return 0;
}

解释一下exgcd1的递推式。

d是最大公约数,这个在b=0,即上一层a%b=0时找到最大公约数,更新传回即可。

我们x和y都是直接更新地址的,那我们这里的y其实就是传给上一层的x,相当于y=x-(a/b)*y,

因为我们传下来的时候是将x和y颠倒的,那么这里x就和y互换,即y-=(a/b)*x,x还是x,传上去就变成y了。

x即为a%b意义下的逆元。

注意,一个数mod一个数是有可能没有逆元的,这时候x好像是返回1。moreover,如果是有逆元的,解出来的x有可能是负数,这时候你可能需要x=(x+mod)%mod.

求不定方程

(我之前没用Markdown写得真难受)

(这个部分是我学了excrt之后才更新的)

(之前学的真是肤浅而且一团乱麻)

exgcd既然可以求ax+by=gcd的解,那么一定就可以求ax+by=c的解。

假设gcd=gcd(a,b),那么我们先把方程两边同时乘gcd/c,那么是不是就可以求x和y了呢?那么求完之后我们在给他乘回去不就行了?

那就行了。

判断无解的情况:如果求出来的gcd并不能被c整除,说明在数论范围内它无解。

鉴于不定方程的性质,x的最小正整数解是在b意义下取模的,y的最小正整数解是在a意义下取模的。我们就可以求出x,y的最小整数解和整数解的个数。因为x和y的增减性是相反的,我们也就可以相应算出最大值。

P5656洛谷模板

#include<bits/stdc++.h>
#define int long long //watch out!
using namespace std;
inline int read()
{
int x=0,w=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
inline void write(int x)
{
if(x>9)write(x/10);
putchar(x%10+'0');
}
inline void exgcd(int a,int b,int& d,int& x,int& y){
if(!b)d=a,x=1,y=0;
else exgcd(b,a%b,d,y,x),y-=(a/b)*x;
}
inline void solve(int a,int b,int c)
{
int cnt=0,miny,maxy,minx,maxx;
int gcd,x,y;
exgcd(a,b,gcd,x,y);
if(c%gcd!=0){printf("-1\n");return;}
a/=gcd;b/=gcd;c/=gcd;//这里学习了一下大佬的做法,将所有答案除以gcd,实际上是一样的,不过下面的x和y就不是乘c/gcd了。
x*=c;
y*=c;
minx=x>0&&x%b!=0?x%b:x%b+b;
maxy=(c-minx*a)/b;
miny=y>0&&y%a!=0?y%a:y%a+a;
maxx=(c-miny*b)/a;
if(maxx>0)cnt=(maxx-minx)/b+1;
if(cnt==0)printf("%d %d\n",minx,miny);
else printf("%d %d %d %d %d\n",cnt,minx,miny,maxx,maxy);
}
signed main()
{
int t=read();
while(t--){
int a=read(),b=read(),c=read();
solve(a,b,c);
}
return 0;
}

扩展欧几里得(exgcd)-求解不定方程/求逆元的更多相关文章

  1. 同余问题(一)——扩展欧几里得exgcd

    前言 扩展欧几里得算法是一个很好的解决同余问题的算法,非常实用. 欧几里得算法 简介 欧几里得算法,又称辗转相除法. 主要用途 求最大公因数\(gcd\). 公式 \(gcd(a,b)=gcd(b,a ...

  2. 浅谈扩展欧几里得[exgcd] By cellur925

    关于扩展欧几里得从寒假时就很迷,抄题解过了同余方程,但是原理并不理解. 今天终于把坑填上了qwq. 由于本人太菜,不会用markdown,所以这篇总结是手写的(什么).(字丑不要嫌弃嘛) ****** ...

  3. poj 1061 扩展欧几里得解同余方程(求最小非负整数解)

    题目可以转化成求关于t的同余方程的最小非负数解: x+m*t≡y+n*t (mod L) 该方程又可以转化成: k*L+(n-m)*t=x-y 利用扩展欧几里得可以解决这个问题: eg:对于方程ax+ ...

  4. 扩展欧几里得(exgcd)与同余详解

    exgcd入门以及同余基础 gcd,欧几里得的智慧结晶,信息竞赛的重要算法,数论的...(编不下去了 讲exgcd之前,我们先普及一下同余的性质: 若,那么 若,,且p1,p2互质, 有了这三个式子, ...

  5. 数论--扩展欧几里得exgcd

    算法思想 我们想求得一组\(x,y\)使得 \(ax+by = \gcd(a,b)\) 根据 \(\gcd(a,b) = \gcd(b,a\bmod b)\) 如果我们现在有\(x',y'\) 使得 ...

  6. 扩展欧几里得 exGCD

    Elementary Number Theory - Extended Euclid Algorithm Time Limit : 1 sec, Memory Limit : 65536 KB Jap ...

  7. 扩展欧几里得,解线性同余方程 逆元 poj1845

    定理:对于任意整数a,b存在一堆整数x,y,满足ax+by=gcd(a,b) int exgcd(int a,int b,int &x,int &y){ ){x=,y=;return ...

  8. 扩展欧几里得 求ax+by == n的非负整数解个数

    求解形如ax+by == n (a,b已知)的方程的非负整数解个数时,需要用到扩展欧几里得定理,先求出最小的x的值,然后通过处理剩下的区间长度即可得到答案. 放出模板: ll gcd(ll a, ll ...

  9. (拓展欧几里得)51NOD 1256 乘法逆元

    给出2个数M和N(M < N),且M与N互质,找出一个数K满足0 < K < N且K * M % N = 1,如果有多个满足条件的,输出最小的.   输入 输入2个数M, N中间用空 ...

随机推荐

  1. 【python学习小知识】求绝对值和numpy和tensor的相互转换

    一.python求绝对值的三种方法 1.条件判断 2.内置函数abs() 3.内置模块 math.fabs 1.条件判段,判断大于0还是小于0,小于0则输出相反数即可 # 法1:使用条件判断求绝对值 ...

  2. 用MAILX 发送邮件

    使用 25 端口发送 mail 编辑/etc/mail.rc 文件,添加以下信息vi /etc/mail.rc set from=xxx@163.com smtp=smtp.163.comset sm ...

  3. Linkerd 2.10(Step by Step)—使用 Kustomize 自定义 Linkerd 的配置

    Linkerd 2.10 系列 快速上手 Linkerd v2 Service Mesh(服务网格) 腾讯云 K8S 集群实战 Service Mesh-Linkerd2 & Traefik2 ...

  4. 【NX二次开发】创建老版的基准平面uf5374

    使用uf5374() 源码: double dP1[3] = { 0.0,0.0,0.0 }; double dP2[3] = { 0.0,1.0,0.0 }; double dP3[3] = { 0 ...

  5. 题解 P3233 [HNOI2014]世界树

    题目传送门 解题思路 正解当然是虚树了. 首先对于原树以及虚树各开一个结构体存边,这个不用多说. 然后我们先 DFS 一遍,求出各个节点的时间戳,子树大小,深度以及父亲节点,并初始化倍增 LCA . ...

  6. 【模拟7.19】那一天我们许下约定(组合数学,DP)

    看了题目名字深切怀疑出题人是不是失恋了,然后出题折磨我们.然后这题就愉快的打了个暴力,最后莫名其妙wa20,伤心..... 其实这题正解不是很难想,如果说把暴力的DP搞出来,正解也差不到哪去了, 我们 ...

  7. 如何在Vue的项目里对element的表单验证进行封装

    介绍需求 熟悉并优化公司项目的第五天,领导说能不能把表单验证封装一下,我打开代码一看 由于是后台管理系统,无数个需要验证的输入框,由于截图长度受限,只能展示部分,类似于这种页面还有无数个!代码重复率非 ...

  8. 关于WLS2中Ubuntu启用SSH远程登录功能,基于Xshell登录,支持Root

    背景介绍 虽然WSL2提供了非常便利的访问Ubuntu目录的形式,但是仍然我们需要通过一个工具,比如XSHELL来实现对Ubuntu的SSH登录. 获取并安装Xshell 7 目前Xshell已经更新 ...

  9. 12、elk的使用(1)

    12.0.架构图: 服务器名称 ip地址 controller-node1(主) 172.16.1.90 slave-node1(从) 172.16.1.91 12.1.elk介绍: (1)ELK是三 ...

  10. 手把手教会你远程Linux虚拟机连接以及配置pytorch环境。

    出一期用于连接远程Ubuntu系统并配置pytorch环境的教学.2021-07-07 13:35:57- 现在的矿难导致显卡大幅度的涨价对很多要做深度学习领域的小伙伴们非常的不友好,配置设备固然要掏 ...