模拟又炸了,我死亡

$exgcd$(扩展欧几里德算法)用于求$ax+by=gcd(a,b)$中$x,y$的一组解,
它有很多应用,比如解二元不定方程、求逆元等等,
这里详细讲解一下$exgcd$的原理。

了解$exgcd$算法前,需要$gcd$算法做铺垫。gcd,又称辗转相除法,用于计算两个整数 $a,b$ 的最大公约数。

$gcd$函数的基本性质:

$gcd(a,b)=gcd(b,a) $

$gcd(a,b)=gcd(-a,b) $

$gcd(a,b)=gcd(|a|,|b|)$

$gcd(a,b)=gcd(b,a$ $mod$ $b)$

证明一下第四条:

设$k$为整数

设$gcd(a,b) = d$

$a$ $mod$ $b=a-kb$,$k = a/b$

因为$a$ $mod$ $d=0,b$ $mod$ $d=0$

所以$kb$ $mod$ $d=0$,

$a-kb$ $mod$ $d=0$

即$(a$ $mod$ $b)$ $mod$ $d=0$

int gcd(int a,int b){
if(b == ){
return a;
}
return gcd(b,a%b);
}

  gcd  

理解了$gcd$,再来证明为什么$exgcd$可以求出$ax+by=gcd(a,b)$的$x,y$。

当$b=0$时,$gcd(a,b) = a$,$ax+by$ 即 $a*1 + 0*0 = gcd(a,b)$;

$x=1,y=0$(因为$b = 0$,$y$的值其实不重要,这里就写成$0$)

因为$gcd(a,b) =  ax+by$,$gcd(b,a$ $mod$ $b) = ax'+ by'$,

每次递归时,$gcd(a,b) = gcd(b,a$ $mod$ $b)$,所以$ax+by = ax'+ by'$,

并且已知 $a%b = a-(a/b)*b$,那么可以得到

$ax'+ by'$

$= bx + (a$ $mod$ $b)y $

$= bx + (a-a/b*b)y $

$= bx + ay - (a/b)*by $

$= ay + b(x-(a/b)*y) $

$x'=y$; $y'=x-(a/b)*y $

int exgcd(int a,int b,int &x, int &y) {
if(b == ) {
x=,y=;
return a;
}
int ans = exgcd(b,a%b,x,y);
int tx = x;
x = y;
y = tx-a/b*y;
return ans;
}

  exgcd  

明白了$exgcd$的原理,思考它如何求解形如$ax+by=c$的不定方程。

设$k$为整数,

设$c=k*gcd(a,b)$

$ax+by=gcd(a,b)$,

两边同乘$k$,得

$k*ax+k*by=k*gcd(a,b)=c$

所以$c$一定为$gcd(a,b)$的倍数。若$c$ $mod$ $gcd(a,b) ≠ 0$,则方程无整数解。

此时的$x'=kx=c/gcd(a.b)*x$。

可以发现,$ax+by=c$ (x∈Z*,y∈Z*)  成立的充要条件是$gcd(a,b)|c$。这个定理叫做裴蜀定理
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
using namespace std; int n,x,sum; int gcd(int a,int b) {
if(!b) return a;
return gcd(b,a%b);
} int main() {
scanf("%d",&n);
sum = ;
for(int i = ; i <= n; i++) {
scanf("%d",&x);
if(x < ) x = -x;
sum = gcd(sum,x);
}
printf("%d",sum);
return ;
}

裴蜀定理

那么,怎么保证x是最小正整数呢?

设$k$为整数,   

   $ax+by$

  $= ax + by + k*ab - k*ab$

  $= a(x+kb) + b(y-ka)$

也就是说,当$x$改变$b$的整数倍时,原式的值可以保持不变;

那么最小正整数即为$x$ $mod$ $b$;

但是要考虑$x$为负数的情况,就要先将$x$加上$b$,直到$x$为正数,再取模,可以得到$x = (x$ $mod$ $b+b)$ $mod$ $b$

综上所述,

$x=(x*c/gcd(a,b)$ $mod$ $b+b)$ $mod$ $b$

int exgcd(int a,int b,int &x, int &y) {
if(b == ) {
x=,y=;
return a;
}
int ans = exgcd(b,a%b,x,y);
int tx = x;
x = y;
y = tx-a/b*y;
return ans;
} int main() {
scanf("%d%d%d",&a,&b,&c);
if(a<) {
a = -a;
c = -c;
}
exgcd(a,b,x,y);
if(c%ans!=)
printf("Impossible");
else
printf("%d",(x*(c/ans))%(b/ans)+(b/ans))%(b/ans));
return ;
}

  解二元不定方程 

模板题:Luogu P1516 青蛙的约会

设跳了$X$次,

由题意得,$m*X+x=n*X+y$ $(mod$ $l)$

$(m-n)*X=y-x$ $(mod$ $l)$

$(m-n)*X-l*Y=y-x$

令$m-n=a$,$l=b$,$y-x=c$,$Y=-Y$

则有$aX+bY=c$

注意负数的情况:若$m-n<0$,则变成了前面的追后面的

$a=n-m$,$c=(x+l-y)$ $mod$ $l=x-y$

即$a=-a,c=-c$

#include<cstdio>
#define int long long
int x,y,m,n,l,a,b,c,x0,y0,g,tmp; int exgcd(int a,int b,int &x, int &y) {
if(b == ) {
x=,y=;
return a;
}
int ans = exgcd(b,a%b,x,y);
int tx = x;
x = y;
y = tx-a/b*y;
return ans;
} main() {
scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l);
a=n-m;
b=l;
c=x-y;
if(a<)
a=-a,c=-c;
int g = exgcd(a,b,x0,y0);
if(c%g!=)
printf("Impossible");
else
printf("%lld",(c/g*x0%(b/g)+b/g)%(b/g));
}
												

Re:Exgcd解二元不定方程的更多相关文章

  1. ecgcd(解二元不定方程)

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=775 关于扩展欧几里得算法还是推一遍好啦: 有方程:a*x+b*y=d=gcd(a, b) ...

  2. exgcd 解同余方程ax=b(%n)

    ax=n(%b)  ->   ax+by=n 方程有解当且仅当 gcd(a,b) | n ( n是gcd(a,b)的倍数 ) exgcd解得 a*x0+b*y0=gcd(a,b) 记k=n/gc ...

  3. Java实现 蓝桥杯VIP 算法提高 解二元一次方程组

    算法提高 解二元一次方程组 时间限制:1.0s 内存限制:256.0MB 问题描述 给定一个二元一次方程组,形如: a * x + b * y = c; d * x + e * y = f; x,y代 ...

  4. 使用代数方程库 Algebra.js解二元一次方程

    假设二元一次方程如下: x + y = 11 x - y = 5 解方程如下: <!DOCTYPE html> <html lang="zh-CN"> &l ...

  5. POJ 2891 Strange Way to Express Integers | exGcd解同余方程组

    题面就是让你解同余方程组(模数不互质) 题解: 先考虑一下两个方程 x=r1 mod(m1) x=r2 mod (m2) 去掉mod x=r1+m1y1   ......1 x=r2+m2y2   . ...

  6. HDU 4793 Collision (解二元一次方程) -2013 ICPC长沙赛区现场赛

    题目链接 题目大意 :有一个圆硬币半径为r,初始位置为x,y,速度矢量为vx,vy,有一个圆形区域(圆心在原点)半径为R,还有一个圆盘(圆心在原点)半径为Rm (Rm < R),圆盘固定不动,硬 ...

  7. nyoj 64-鸡兔同笼 (解二元一次方程)

    64-鸡兔同笼 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:26 submit:58 题目描述: 已知鸡和兔的总数量为n,总腿数为m.输入n和m, ...

  8. c语言解二元二次方程组

    设a和b是正整数 a+b=30 且a*b=221 求a和b的值 思路就是穷举a和b的值,每次得到a和b的一个值,看是否同时满足a+b=30且a*b=221,如果满足,那么就输出. 那么a和b的的取值范 ...

  9. VBA Promming——分支语句(解二元一次方程)

    分支语句 If expression1 Then expressions ElseIf expression2 Then expressions Else expression End If 注:VB ...

随机推荐

  1. 【ASP.NET Core快速入门】(八)Middleware管道介绍、自己动手构建RequestDelegate管道

    中间件是汇集到以处理请求和响应的一个应用程序管道的软件. 每个组件: 可以选择是否要将请求传递到管道中的下一个组件. 之前和之后调用管道中的下一个组件,可以执行工作. 使用请求委托来生成请求管道. 请 ...

  2. 【ASP.NET Core快速入门】(四)在CentOS上安装.NET Core运行时、部署到CentOS

    下载.NET Core SDK 下载地址:https://www.microsoft.com/net/download/windows 第一步:Add the dotnet product feed( ...

  3. 环境与工具1:微信群刷屏 | itchat

    在微信群里面,"刷屏"的行为是被谴责的,伴随着"快发红包道歉"与"送飞机票"的出现.那如果小程硬是要做到"刷屏"来验证自 ...

  4. 第28章 确认(Consent) - Identity Server 4 中文文档(v1.0.0)

    在授权请求期间,如果IdentityServer需要用户同意,则浏览器将被重定向到同意页面. 同意用于允许最终用户授予客户端对资源(身份或API)的访问权限.这通常仅对第三方客户端是必需的,并且可以在 ...

  5. [心得] SQL Server Partition(表分區) 資料分佈探討

    最近在群裡有個朋友問了個問題是這樣的 用户表有一千多万行,主键是用户ID,我做了分区.但经常查询时,其它的表根据用户ID来关联,这样跨区查询,reads非常高.有什么好的处理办法?不分区的话,索引维护 ...

  6. 一篇文章搞定SpringMVC参数绑定

    SpringMVC参数绑定,简单来说就是将客户端请求的key/value数据绑定到controller方法的形参上,然后就可以在controller中使用该参数了 下面通过5个常用的注解演示下如何进行 ...

  7. 教我徒弟Android开发入门(四)

    本期知识点: 两大常用布局的简单介绍 在我们的APP使用第三方库 Android Studio常用快捷键 一.两大常用布局 1.LinearLayout线性布局 线性布局,可以垂直显示或者水平显示,设 ...

  8. 快速使用CSS Grid布局,实现响应式设计

    常用Grid布局属性介绍 下面从一个简单Grid布局例子说起. CSS Grid 布局由两个核心组成部分是 wrapper(父元素)和 items(子元素). wrapper 是实际的 grid(网格 ...

  9. Shell基础命令(一)

    Shell 教程 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程序提供了一个 ...

  10. Dynamics CRM Web API中的and和or组合的正确方式!

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复243或者20170111可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...