当前位置: 首页 > news >正文

洛谷题单指南-进阶数论-P1516 青蛙的约会

原题链接:https://www.luogu.com.cn/problem/P1516

题意解读:长L的环形数轴,初始A在x坐标、一次跳m米,B在y坐标、一次跳n米,问最少跳几次AB相遇。

解题思路:

1、欧几里得算法

欧几里得算法(Euclidean Algorithm),又称辗转相除法,是数学中用于求解两个正整数最大公约数(Greatest Common Divisor, GCD) 的经典算法。其核心优势在于通过 “不断用较大数除以较小数,替换原数对为‘除数’和‘余数’” 的迭代过程,快速缩小数值规模,最终得到最大公约数。

欧几里得算法的可用递归描述为:对任意非负整数a和任意整数b,gcd(a,b) = gcd(b, a mod b)

证明:

设d|a且d|b,设a = bq + r,r = a mod b,r = a - bq则有d|r,即d | a mod b,因此a、b的约数也是b、a mod b的约数;

设d|b且d|a mod b,由a = bq + a mod b则有d|a,因此b、a mod b的约数也是a、b的约数;

综上,a,b和b,a mod b的约数相同,则最大公约数也一样,因此gcd(a,b) = gcd(b, a mod b)

代码:

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

2、扩展欧几里得算法

扩展欧几里得算法(Extended Euclidean Algorithm)是欧几里得算法(辗转相除法)的延伸,其核心价值不仅在于计算两个整数的最大公约数(gcd),更在于能找到满足裴蜀定理的一组整数解 —— 即对任意整数 ab,存在整数 xy 使得 ax + by = gcd(a, b)

其过程为:

设𝑎𝑥1 +𝑏𝑦1 = gcd(𝑎,𝑏),𝑏𝑥2 +(𝑎 mod 𝑏)𝑦2 = gcd(𝑏,𝑎 mod 𝑏)

由欧几里得定理可知:gcd(𝑎,𝑏) = gcd(𝑏,𝑎 mod 𝑏)

所以 𝑎𝑥1 +𝑏𝑦1 = 𝑏𝑥2 + (𝑎 mod 𝑏)𝑦2

又因为 𝑎 mod 𝑏 = 𝑎 − (⌊𝑎/𝑏⌋ ×𝑏)

所以 𝑎𝑥1 +𝑏𝑦1 = 𝑏𝑥2 +(𝑎 −(⌊𝑎/𝑏⌋ × 𝑏))𝑦2

𝑎𝑥1 +𝑏𝑦1 = 𝑎𝑦2 +𝑏𝑥2 −⌊𝑎/𝑏⌋ × 𝑏𝑦2 =𝑎𝑦2 + 𝑏(𝑥2 −⌊𝑎/𝑏⌋𝑦2)

所以 𝑥1 =𝑦2, 𝑦1 = 𝑥2 −⌊𝑎/𝑏⌋𝑦2

在递归过程中,x1,y1是上一层的x、y,x2、y2是下一层的x、y,当a mod b ==0时,此时的b即最大公约数,那么bx+0y=b,因此x=1 y=0是递归出口。

代码:

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, y, x); //递归时上一层的x1=下一层的y2,上一层的y1 = 下一层的x2y -= a / b * x; //此时x1是下一层的y2,y1是下一层的x2,这句话的意思就是y1 = x2 - a / b * y2return d;
}

3、二元一次不定方程的通解

对于a、b是正整数,ax + by = c有解的条件是d | c,其中d = gcd(a, b),通过扩展欧几里得算法可以求得ax + by = d的解,设为x0,y0

那么ax + bx = c一个特解就是x1 = x0 * c / d, y1 = y0 * c / d

设k为任意整数,则ax + bx = c的通解可以表示为:x = x1 + (b / d) * k,y = y1 - (a / d) * k

要解x的最小正整数解,用(x1 % (b/d) + (b/d)) % (b/d)即可。

3、问题分析

经过时间t之后,A所在的位置变成(mt + x) % L,B所在位置变成(nt + y) % L

A、B要相遇,必须满足(mt + x) % L = (nt + y) % L,用同余表示即mt + x ≡ nt + y (mod L),

令设整数s,有mt + x + Ls = nt + y

进而(m - n)t + Ls = y - x

另a = |m - n|, b = L, c = (m > n ? 1 : -1) * (y - x)

求方程at + bs = c中t的最小正整数解即可

扩展欧几里得算法即可解决。

100分代码:

#include <bits/stdc++.h>
using namespace std;typedef long long LL;
LL x, y, m, n, L;LL exgcd(LL a, LL b, LL &x, LL &y)
{if(b == 0){x = 1, y = 0;return a;}LL d = exgcd(b, a % b, y, x);y -= a / b * x;return d;
}int main()
{cin >> x >> y >> m >> n >> L;LL a = abs(m - n), b = L, c = (m > n ? 1 : -1) * (y - x);LL s, t;LL d = exgcd(a, b, t, s);if(c % d){cout << "Impossible";return 0;}t *= (c / d);cout << (t % (b / d) + (b / d)) % (b / d);return 0;
}

 

http://www.gsyq.cn/news/9689.html

相关文章:

  • electron中的几个概念
  • 保护眼睛小程序
  • 001_string操作
  • hbase 面试题
  • mall项目学习笔记
  • 存储多边形网格的文件格式:OBJ、FBX、RenderMan、glTF、USD 等。
  • 实用指南:Unity 游戏引擎中 HDRP(高清渲染管线) 的材质着色器选择列表
  • 安防监控中常见的报警类型有哪些?国标GB28181平台EasyGBS的报警能力解析
  • LAMP 环境一键部署脚本(Apache+MySQL+PHP) - 实践
  • 【ubuntu24.04】NFS机械硬盘无法挂载成功 - 实践
  • VTable-Sheet:重新定义Web电子表格的开源解决方案
  • Coolmuster Android Assistant:Windows架构下的Android设备管理专家
  • Linux服务器单网卡如何配置多个的IP地址?
  • day38大模型程序开发-GraphRAG实操
  • 深入解析MS12-020关键漏洞CVE-2012-0002:远程桌面协议的安全风险与缓解方案
  • 鸿蒙项目实战(九):get请求参数的处理
  • 20250806_信安一把梭_test
  • 专业 RAW 图像处理利器!DxO PhotoLab 让你的照片质感飙升
  • mysql时间转字符串,自定义格式将日期时间值转换为字符串
  • 其他与其它的区别
  • 实用指南:数据库造神计划第十七天---索引(2)
  • 指令流水线
  • nuget控制台乱码的解决办法
  • WPF TextBlock effect DropShadrowEffect,BlurEffect
  • 在控制台执行这段代码可以列出所有::selection规则
  • 超前探展!2025 云栖大会朋友圈晒图必备
  • 进程池
  • 报表神器Stimulsoft再升级!Stimulsoft Reports、Dashboards 和 PDF Forms 2025.4 即将发布!
  • 数显LED驱动芯片恒流数码管驱动IC内置显示RAM为816位 VK16D33
  • 【AI智能体】Dify 搭建数据分析应用实战操控详解