gcd算法以及exgcd

2023-05-16

1.欧几里得算法

欧几里得是求最大公约数的经典算法,又称辗转相除法。
gcd函数就是用来求(a,b)的最大公约数的。
gcd函数的基本性质:
gcd(a,b)=gcd(b,a)=gcd(-a,b)=gcd(|a|,|b|)
gcd(a,b)=gcd(b,a mod b)


证明:a可以表示成a = kb + r,则r = a mod b
	 假设d是a,b的一个公约数,
	 则有 d | a , d | b ,而r = a - kb,
	 因此 d | r 因此d是(b,a mod b)的公约数
	 假设d 是(b,a mod b)的公约数,
	 则 d | b , d | r ,但是a = kb +r
	 因此d也是(a,b)的公约数
	 因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证
  

所以通过递归,最终可以使得其中一个参数为零,则另一个不为零的数则为最大公约数
板子如下:

typedef long long ll;
ll gcd(ll a,ll b){
	return b==0?a:gcd(b,a%b);
}

当然也可以求最小公倍数
最小公倍数lcm=a * b/gcd(a,b)

2.扩展算法

1.解ax+by=gcd(a,b)

对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然
存在整数对 x,y ,使得 gcd(a,b)=ax+by。


求解 x,y的方法的理解:
	设 a>b。
1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;
2,a>b>0 时:
	设 ax1+ by1= gcd(a,b);
	bx2+ (a mod b)y2= gcd(b,a mod b);
根据朴素的欧几里德原理有 gcd(a,b) = gcd(b,a mod b);
	则:ax1+ by1= bx2+ (a mod b)y2;
	即:ax1+ by1= bx2+ (a - [a / b] * b)y2=ay2+ bx2- [a / b] * by2;
说明: 
	a-[a/b]*b即为mod运算。[a/b]代表取小于a/b的最大整数。
也就是ax1+ by1 == ay2+ b(x2- [a / b] *y2);
根据恒等定理得:
		x1=y2;
		y1=x2- [a / b] *y2;
这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.
上面的思想是以递归定义的,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以结束。  

板子如下:

int gcd(int a,int b,int &x,int &y){
    if (b==0){
        x=1,y=0;
        return a;
    }
    int q=gcd(b,a%b,y,x);
    y-=a/b*x;
    return q;
}

可以这样思考:
对于a’=b,b’=a%b 而言,我们求得 x, y使得 a’x+b’y=Gcd(a’,b’)
由于b’=a % b=a - a / b * b
(这里的 / 是程序设计语言中的除法)
那么可以得到:
ax+by=gcd(a,b) =>
bx+(a - a / b * b)y = gcd(a’, b’) = gcd(a, b) =>
ay +b(x - a / b * y) = Gcd(a, b)
因此对于a和b而言,他们的相对应的p,q分别是 y和 (x-a/b*y)。
板子如下:

nt gcd(int a,int b,int &x,int &y){
    if (b==0){
        x=1,y=0;
        return a;
    }
    int q=gcd(b,a%b,x,y);
    int t=x;x=y;
    y=t-a/b*y;
    return q;
}
2.解ax+by=c

使用扩展欧几里德算法解决不定方程的办法
对于不定整数方程pa+qb=c,若 c mod Gcd(a, b)=0,则该方程存在整数解,
否则不存在整数解。
通过上面的程序即可求出一组x,y使得gcd(a,b)=ax+by
找其所有解的方法如下:
在找到x * a+y * b = Gcd(a, b)的一组解x0,y0后,
可以得到x * a+y * b = c的一组解:
x1 = x0 * (c/Gcd(a,b)),
y1 = y0 * (c/Gcd(a,b)),

3.解集

假设我们得出ax+by=c一组解x与y,如果x每减去一个t(t为常数),
那么y至少必须加上一个a’* t/b’
(其中a’=a/gcd(a,b),b’=b/gcd(a,b)),
才能使等式两边成立,即
  a(x-t)+b(y+a’ * t/b’)=ax+by=c
由于我们需要变换后的x和y仍然是整数,由于t已经是整数,即x-t也一定是整数,
现在只需考虑a’ * t/b’是否为整数,由于gcd(a’,b’)=1,
即a’一定不是b’的倍数,故必须令t=t * b’(即c必须是b’的倍数),才使得a’ * t/b’为整数,即解集为:
  x=x-t * b/gcd(a,b),y=y+t * a/gcd(a,b),t为任意整数
特别的,当gcd(a,b)=1,解集为:x=x-t * b,y=y+t * a

练习

1.扩展gcd-时间复杂性

题目内容:
计算循环语句的执行频次 for(i=A; i!=B ; i+=C) x+=1;
其中A,B,C,i都是k位无符号整数。

输入描述

A B C k, 其中0<k<32

输出描述

输出执行频次数,如果是无穷,则输出“forever”

输入样例

3 7 2 16

输出样例

2

k位无符号整数则数据范围为0~2k(具体含义可以搜索无符号整数溢出)
所以设y,题目意思可以理解为
A+x * C - B=y * 2k => x * C+y * 2k=B-A
于是可以用exgcd求解
令a=C,b=2k,c=B-A
首先判断B-A 是否是gcd(a,b)倍数,如果不是则无法求出一组x。
求出一组x0,y0后,则通解为
x=x0 * a/gcd(a,b)*t
y=y0 - b/gcd(a,b)*t

令n=a/gcd(a,b),m= b/gcd(a,b)
则可以得到
①x0 * a+y0 * b=c
②a(x0+n * t)+b(y0-m * t)=c
联立上式
可得
a * t * n - b * t * m = 0
a * n - b * m=0
也就是a * n=b * m,要想n,m最小就是使得a * n,b * m都为a,b的最小公倍数:
a * n = (a * b)/gcd(a,b) => n = b/gcd(a,b);
同理:m = a /gcd(a,b);
则:
x0 = (x % n + n)%n
y0 = (y % m + m)%m

#include<iostream>
using namespace std;
//A + xC - B = y * 2^k
int exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1;y=0;
		return a;
	}
		int d=exgcd(b,a%b,x,y);
		int t=x;
		x=y;
		y=t-a/b*y;
	return d;
}
int main(){
	int A,B,C,k;
	cin >> A >> B >> C >> k;
	//特判A=B=C=K=0 
	if(A==0&&A==B&&B==C&&C==k) return !(cout << "forever");
	int b=1<<k,a=C,c=B-A,x=10,y=10;
	int d=exgcd(a,b,x,y);
	if(c%d){
		return !(cout << "forever");
	} 
	x=(x*(c/d))%b;
	x=(x%(b/d)+(b/d))%(b/d);//防止出现负数解
	cout << x;
	return 0;
} 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gcd算法以及exgcd 的相关文章

  • 快速搭建私有pip镜像源

    1 快速体验 span class token keyword import span os span class token keyword import span sys span class token keyword import
  • 虚拟机Ubuntu18.04突然连不上网怎么解决

    本来正常使用ubuntu18 04 xff0c 突然连不上网 使用sudo apt get update无法连接到域名 采用如下方法解决 xff01 xff01 xff01 原文链接 xff1a https blog csdn net qq
  • rpm方式安装 mysql5.7.29

    一 rpm方式安装 mysql5 7 29 1 下载mysql5 7 29的rpm安装包 rpm的mysql包 安装起来简单 解压版的mysql还需要做许多配置 xff0c 稍有不慎就会出错 xff01 xff01 xff01 下载地址 x
  • 必须知道的C语言知识细节:函数形参和实参的区别

    当你选择了一种语言 xff0c 意味着你还选择了一组技术 一个社区 Joshua Bloch C语言中函数形参和实参是十分重要的概念 xff0c 初学者很容易混淆 形参 xff1a 顾名思义 xff0c 形式参数 xff0c 仅仅是声明了参
  • windows和虚拟机互传文件的三种方式

    大家好 xff0c 在平时学习工作的时候可能有这样的需求 xff1a 要将windows中的文件传到虚拟机中或者将虚拟机的文件传到windows xff0c 大家都是怎么实现的呢 xff1f 今天给大家介绍下windows和虚拟机互传文件的
  • dpkg命令详解

    用法 xff1a dpkg lt 选项 gt lt 命令 gt Commands i install lt deb file name gt R recursive unpack lt deb file name gt R recursiv
  • 结构体字节对齐之嵌套结构体

    搜狐畅游2020游戏研发笔试题目 xff1a 以下输出的结果是 xff1f xff1f xff1f span class token macro property span class token directive keyword inc
  • 程序设计CSP-M4-补题——T1-TT数鸭子

    T1 TT数鸭子 题目描述InputOutput解题思路实现代码总结 题目描述 给出n个数 xff0c 求有多少个数其数位中不同的数字的个数小于k Input 第一行两个数n k 第二行n个数 Output 输出满足题目要求的数字个数 解题
  • ceph 分布式 存储服务 恢复

    文章目录 一条命令执行恢复 xff08 你最好还是读读 为什么可以一条命令恢复 ceph 服务 xff09 版本信息ceph 容器服务恢复前提条件安装cephadm查看ceph 服务依赖删除多余的集群 可选 一条命令执行恢复 systemc
  • svn: E230001: Server SSL certificate verification failed: certificate issued

    svn E230001 Server SSL certificate verification failed certificate issued 字面上的大致意思是服务器的SSL证书验证失败 解决方法 xff1a 在终端执行svn ls
  • linuxQt程序打包

    linux程序打包 qt程序打包与执行 将release版本生成的移动到新建文件夹中 xff1b linux下qt打包的sh文件 例如 xff0c 生成pack sh span class token shebang important b
  • JAVA判断时间格式为 “YYYY-MM-DD“

    常用的方法如下 xff1a import java text DateFormat import java text SimpleDateFormat import java util Date public class DataTest
  • win系统修改右键新建菜单

    win系统修改右键新建菜单 在右键新建中添加自己想要的文件修改右键新建顺序修改右键新建中菜单项的名字 在右键新建中添加自己想要的文件 首先win 43 R再regedit调出注册表在HKEY CLASSES ROOT目录下找到对应后缀名 x
  • Django基础(一)

    目录 创建项目 创建一个应用 启动服务 创建项目 D pythonProject3 Django gt django admin startproject hello 执行完成命令 大概10s之后会出现一个以hello命名的文件夹 创建一个
  • 二分图多重匹配——小结

    二分图的重匹配 xff0c 说白了就说一对多的匹配 还是匈牙利算法 xff0c 一般都是给出两个集合 xff0c 然后让你对这两个集合进行匹配 xff0c 但是其中一个集合是可以多次匹配的 xff0c 但是匹配的次数是有限的 xff08 假
  • C.Garland(DP)

    题目链接 xff1a C Garland 题意 给你了一个序列 xff0c 包含n个数 xff0c 这个序列是由1 n数字构成 xff0c 但是题目给你的这个序列并不完整 xff0c 让你去补完整 xff0c 那些输入的值为0的位置的就是让
  • P1908 逆序对(离散化)

    洛谷P1908 逆序对 逆序对就不用解释了 xff0c 题上也说的很清楚 那我分别用归并排序和树状数组来解决一下这道题目 归并排序 我们都知道 xff0c 归并排序是通过把大区间一直分 xff0c 分成小区间 xff0c 然后小区间排序好了
  • Codeforces Round #618 (Div. 2)

    太菜了 xff0c 也只能补补题了 A Non zero 这道题瞎弄一下就过了 xff0c 数0的个数 xff0c 把0全变成1 xff0c 然后再判断现在和是不是0 xff0c 和是0的话就再加上1 span class token ma
  • HDU 1025最长递增子序列(二分法)

    最长递增子序列 xff08 二分 xff09 HDU1025 https www felix021 com blog read php 1587 找最长递增子序列 xff0c 以前一般用DP的方法找 xff0c 因为理解简单 xff0c 实
  • Codeforces Round #658 (Div. 2)

    比赛链接 xff1a https codeforces com contest 1382 A Common Subsequence 题意 给你两组数 xff0c 问你有没有相同 的书 xff0c 有的话 xff0c 输出最短的那组 xff0

随机推荐

  • mysql学习笔记之数据库

    我的mysql学习参考于github文章 数据库 xff1a 高效的存储和处理数据的介质 xff08 比如磁盘和内存 xff09 xff0c 又根据介质的不同 xff0c 分为关系数据库和非关系数据 关系数据库特点 xff1a 1 xff0
  • Python_pytorch (三)分解网络模型

    python pytorch 小土堆pytotch学习视频链接 from的是一个个的包 xff08 package import 的是一个个的py文件 file py 所使用的一般是文件中的类 class 第一步实例化所使用的类 然后调用类
  • Python_pytorch(四)网络搭建

    搭建架构 span class token keyword import span torch span class token keyword import span torchvision span class token keywor
  • Python_pytorch(五)模型训练

    反向传播 Loss Function span class token keyword import span torchvision span class token keyword from span torch span class
  • 【计蒜客】泥塑课C++

    泥塑课 描述 小米是一个幼儿园老师 xff0c 每学期的泥塑课上 xff0c 她都会给每个学生发不超过 250 立方厘米的等量橡皮泥 xff0c 教大家做泥塑 在上课过程中 xff0c 她发现每个班都恰好有一个小朋友会去抢另一个小朋友的橡皮
  • linux无法粘贴文件

    无粘贴功能的主要原因是无权限复制 xff0c 所以解决方案是 xff1a 打开终端 xff0c 输入 xff1a sudo nautilus 那么就会打开一个有管理员权限的文件夹资源器 xff0c 现在右键就有粘贴功能了
  • Zookeeper详解(三)——开源客户端curator

    开源客户端curator true re de curator是Netflix公司开源的一个zookeeper客户端 xff0c 后捐献给apache xff0c curator框架在zookeeper原生API接口上进行了包装 xff0c
  • mysql 修改字段类型

    修改字段类型 xff1a span class token keyword alter span span class token keyword table span 表名 span class token keyword modify
  • 【python】字符串(二)

    今天我们来学习如何判断字符串格式的内容 xff0c 针对基础判断 文章目录 一 基础知识二 例题 xff08 一 xff09 找元音 xff08 二 xff09 判断电话号码合法 一 基础知识 我们先来看看一般会用到那些知识点 xff1a
  • CentOS7 个性化

    CentOS美化 前言一 上图看效果原生桌面效果图美化后的效果图 二 使用步骤1 安装相关的包2 调整主题和字体 总结 前言 咳咳咳 xff5e 无论什么系统 xff0c 美化是必不可少的 xff0c 可以没用 xff0c 但不能没有 xf
  • freeswitch 1.10版本 centos7安装

    文章目录 简介安装使用ODBC连接mysql可能出现的问题 简介 FreeSWITCH 是一个电话的软交换解决方案 xff0c 包括一个软电话和软交换机用以提供语音和聊天的产品驱动 FreeSWITCH 可以用作交换机引擎 PBX 多媒体网
  • Airsim_API

    AirSim API 参考自知乎大佬https www zhihu com column multiUAV 讲的非常好 xff01 无人机姿态角 pitch是俯仰角 xff0c 是 点头 yaw是偏航角 xff0c 是 摇头 roll是旋转
  • JWT详解

    JWT详解 什么是JWTJWT能做什么JWT的认证流程JWT认证的优势JWT结构 1 Header 2 Payload 3 Signature Java中使用JWT实际开发中的应用 Springboot 43 Spring Security
  • Java获取天气情况的方式

    说明 经过搜集和参考网上的相关资料 xff0c Java获取天气情况数据的通用步骤如下 xff1a 调用天气接口api xff1b 解析返回的XML 或 JSON数据 xff1b 这里我并不去用代码实现一个Demo xff0c 而是记录一下
  • Epoll的两种工作模式

    Epoll的两种工作模式 LT模式 xff08 水平触发 xff09 假设委托内核检测读事件 检测fd的读缓冲区 都缓冲区有数据 epoll检测到了会给用户通知 用户不读数据 xff0c 数据一直在缓冲区 xff0c epoll会一直通知用
  • QT环境搭建:解决在linux上Qt的模块缺失问题

    Qt的媒体模块 Qt multimedia 缺少模块multimedia的问题 解决 sudo apt install libqt5multimedia qtmultimedia5 Unknown module s in QT serial
  • QT基础入门【环境搭建篇】Linux(ARM架构)下的QT开发环境搭建

    目录总览 QT基础入门目录总览 在 架构下安装 开发环境有两种方式 一是编译 官方静态库 比较费时间 有很多未知错误 二是通过源的方式安装 开发环境 本文采用第二种办法 安装QT5 sudo apt get install qt5 defa
  • QT基础入门【调试篇】QT远程部署与调试嵌入式ARM开发板

    目录总览 QT基础入门目录总览 一 环境配置 nbsp 1 根据开发板完成交叉编译链以及GDB的配置 因开发板而异 首先在虚拟机上配置好开发板厂家提供的交叉工具编译链 之后在qtcreator中添加交叉编译链以及GDB的配置 1 1 设置交
  • Mysql密码忘记怎么办?重置密码完整教程

    新手经常会在安装完Mysql时密码设置错误 xff0c 导致登录不进去的问题 xff0c 这就需要重置MySQL数据库的密码了 1 首先打开cmd命令行 xff0c 执行net stop mysql xff0c 把mysql服务先关掉 xf
  • gcd算法以及exgcd

    1 欧几里得算法 欧几里得是求最大公约数的经典算法 xff0c 又称辗转相除法 gcd函数就是用来求 a b 的最大公约数的 gcd函数的基本性质 xff1a gcd a b 61 gcd b a 61 gcd a b 61 gcd a b