洛谷P1516 青蛙的约会(扩展欧几里德)

洛谷题目传送门

很容易想到,如果他们相遇,他们初始的位置坐标之差xy和跳的距离(nm)t(设t为跳的次数)之差应该是模纬线长l同余的,即(nm)txy(modl)

转化一下,不就变成了让我们求一个不定方程(nm)t+kl=xy(kZ)t的最小非负整数解么?

a=nm,b=l,c=xy,把它转化成我们比较熟悉的一般不定方程的形式ax+by=c(此式的x,y与题目给的坐标意义不同)

首先,设g=gcd(a,b)我们可以通过扩欧求出ax0+by0=gx0的一个解

这时,因为ax+byg为整数,所以cg也必须是整数,否则无解

否则,等式两边同乘cg,得acx0g+bcy0g=c

那么,x=cx0g就是ax+by=cx的一个解

如何由一个解得到其它解呢?有一个恒等式a(x+db)+b(yda)=c

在保证db,da都是整数的情况下,我们让d最小,就可以得到所有的整数解,那么d=1g

如果解出的x>0,那么最小非负整数解等于xmodbg;否则等于xmodbg+bg

代码就可以直接写(x%(b/g)+b/g)%(b/g)

然后就可以交上去了,发现获得了70分

怎么回事?因为gcd只对非负整数有意义,所以如果a<0等式两边要同时取负,a,c都要变成相反数;b本来就是正数,不用变也不能变。

总之,虽然是裸的exgcd题,但是很容易被细节实现坑到,尤其是求最小非负整数解和处理a为负数的地方。

#include<cstdio>
#define LL long long
LL x,y,m,n,l,a,b,c,x0,y0,g,tmp;
void exgcd(LL a,LL b){
	if(!b){x0=1;g=a;return;}//顺便求gcd
	exgcd(b,a%b);
	tmp=x0;x0=y0;y0=tmp-a/b*y0;
}
int main(){
	scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l);
	a=n-m;b=l;c=x-y;
	if(a<0)a=-a,c=-c;//处理a为负数情况
	exgcd(a,b);
	if(c%g)puts("Impossible");
	else printf("%lld\n",(c/g*x0%(b/g)+b/g)%(b/g));//求最小非负整数解
	return 0;
}
posted @   Flash_Hu  阅读(1993)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示
剑桥
17:14发布
剑桥
17:14发布
5°
西风
7级
空气质量
相对湿度
34%
今天
多云
-3°/5°
周六
-1°/3°
周日
-2°/7°