Re:Exgcd解二元不定方程
模拟又炸了,我死亡
$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$。
#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 ;
}
解二元不定方程
设跳了$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解二元不定方程的更多相关文章
- ecgcd(解二元不定方程)
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=775 关于扩展欧几里得算法还是推一遍好啦: 有方程:a*x+b*y=d=gcd(a, b) ...
- 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 ...
- Java实现 蓝桥杯VIP 算法提高 解二元一次方程组
算法提高 解二元一次方程组 时间限制:1.0s 内存限制:256.0MB 问题描述 给定一个二元一次方程组,形如: a * x + b * y = c; d * x + e * y = f; x,y代 ...
- 使用代数方程库 Algebra.js解二元一次方程
假设二元一次方程如下: x + y = 11 x - y = 5 解方程如下: <!DOCTYPE html> <html lang="zh-CN"> &l ...
- POJ 2891 Strange Way to Express Integers | exGcd解同余方程组
题面就是让你解同余方程组(模数不互质) 题解: 先考虑一下两个方程 x=r1 mod(m1) x=r2 mod (m2) 去掉mod x=r1+m1y1 ......1 x=r2+m2y2 . ...
- HDU 4793 Collision (解二元一次方程) -2013 ICPC长沙赛区现场赛
题目链接 题目大意 :有一个圆硬币半径为r,初始位置为x,y,速度矢量为vx,vy,有一个圆形区域(圆心在原点)半径为R,还有一个圆盘(圆心在原点)半径为Rm (Rm < R),圆盘固定不动,硬 ...
- nyoj 64-鸡兔同笼 (解二元一次方程)
64-鸡兔同笼 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:26 submit:58 题目描述: 已知鸡和兔的总数量为n,总腿数为m.输入n和m, ...
- c语言解二元二次方程组
设a和b是正整数 a+b=30 且a*b=221 求a和b的值 思路就是穷举a和b的值,每次得到a和b的一个值,看是否同时满足a+b=30且a*b=221,如果满足,那么就输出. 那么a和b的的取值范 ...
- VBA Promming——分支语句(解二元一次方程)
分支语句 If expression1 Then expressions ElseIf expression2 Then expressions Else expression End If 注:VB ...
随机推荐
- 【Java基础】【18Map集合&模拟斗D主X排和F排】
18.01_集合框架(Map集合概述和特点) A:Map接口概述 查看API可以知道: 将键映射到值的对象 一个映射不能包含重复的键 每个键最多只能映射到一个值 B:Map接口和Collection接 ...
- iBinary C++STL模板库关联容器之map/multimap
目录 一丶关联容器map/multimap 容器 二丶代码例子 1.map的三种插入数据的方法 3.map集合的遍历 4.验证map集合数据是否插入成功 5.map数据的查找 6.Map集合删除元素以 ...
- javascript入门篇(一)
未定义:undefined 布尔类型值:true,false 判断类型:typeof() 绝对值:Math.abs(-1) 声明常量:const 声明变量:var 小数两值互换如果出现问题,可以通 ...
- linux 制作不用密碼可立即登入的 ssh 用戶
机器环境: 192.167.33.48 clent 用户:server 192.167.33.47 server 用户:server 1.客户端 生成密钥 ssh-keygen 2. 查看密钥文件权限 ...
- [十二]基础数据类型之String
在正式介绍String之前,我们先介绍下CharSequence char + sequence 就是字符的序列的意思 Java中万事万物都是对象类型 而对于字符的序列,也就是多个char, 这么一种 ...
- Xhprof分析php性能
https://windows.php.net/downloads/pecl/releases/xhprof/0.10.6/ 下载Xhprof版本 配置一个本地访问url,指向index.php,能访 ...
- Java开发笔记(三十九)日期工具Date
Date是Java最早的日期工具,编程中经常通过它来获取系统的当前时间.当然使用Date也很简单,只要一个new关键字就能创建日期实例,就像以下代码示范的那样: // 创建一个新的日期实例,默认保存的 ...
- Linux基础:CentOS安装python3.7
1.下载python3 wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz 2.解压 [root@mycentos ~]# ta ...
- Vue UI:Vue开发者必不可少的工具
译者按: Vue开发工具越来越好用了! 原文: Vue UI: A First Look 译者: Fundebug 本文采用意译,版权归原作者所有 随着最新的稳定版本Vue CLI 3即将发布,是时候 ...
- 灵活使用 console 让 js 调试更简单
摘要: 玩转console. 原文:灵活使用 console 让 js 调试更简单 作者:前端小智 Fundebug经授权转载,版权归原作者所有. Web 开发最常用的就是 console.log , ...