【二元不定方程】POJ 青蛙的约会
首先,根据题意,我们可以列出同余方程:
( x + k m ) % L = = ( y + k n ) % L (x+km) \% L= = (y+kn)\%L (x+km)%L==(y+kn)%L
( x + k m ) − ( y + k n ) = a L (x+km)-(y+kn)=aL (x+km)−(y+kn)=aL
(
m
−
n
)
k
+
y
−
x
=
a
L
(m-n)k+y-x=aL
(m−n)k+y−x=aL
这就是一个二元一次不定方程了
可以直接套用exgcd
剩下的有一点点麻烦
题目要求最小的正整数k 所以我们还要找符合条件的这个特解
首先用exgcd搞一个特解出来
利用exgcd解
a
x
+
b
y
=
c
,
d
=
(
a
,
b
)
ax+by=c,d=(a,b)
ax+by=c,d=(a,b)的结论,我们知道x的通解是
x
+
b
d
x+\frac{b}{d}
x+db
在这个解为正整数的条件下 对于每一个解,我们可以快速求出最小正整数解为
(
x
+
b
d
)
%
b
d
(x+\frac{b}{d})\%\frac{b}{d}
(x+db)%db
[可以想成通解是一个等差数列,是最小的那个数加上很多个
b
d
\frac{b}{d}
db 构成的 所以每个解求余
b
d
\frac{b}{d}
db就是原来那个最小解]
所以在用exgcd求出解后 如果特解是负数 我们一直加 b d \frac{b}{d} db知道它为正 就是最小正整数解
如果求出的解本身为正 我们就求余 b d \frac{b}{d} db,就是答案
#include<cstdio>
#include<stack>
#include<cstring>
using namespace std;
#define MAXN 1005
#define LL long long
LL gcd(LL a,LL b)
{
return b?gcd(b,a%b):a;
}
void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
{
LL x0=x,y0=y;
if(b==0)
{
d=a,x=1,y=0;
return ;
}
else
{
exgcd(b,a%b,d,x0,y0);
x=y0;
y=x0-a/b*y0;
}
}
int main()
{
LL x,y,m,n,l;
scanf("%lld %lld %lld %lld %lld",&x,&y,&m,&n,&l);
LL a=m-n,b=l,c=y-x;
if(a<0) a+=l;//把a变成正数 由于是环形 相对位置不改变 不影响结果
LL d=gcd(a,b);
if(c%d!=0)
{
printf("Impossible\n");
return 0;
}
exgcd(a,b,d,x,y);
x=x*(c/d);
while(x<0)
x+=(b/d);
x=x%(b/d);
printf("%lld\n",x);
return 0;
}
另外就是注释的地方 相当于确保a为整数
不知为什么加了这个东西就要快很多 当然加不加在poj上都还是可以过
此题在HihoCoder上也有一个比较相似的题目,可以了解一下 感觉这个网站上的提示还比较到位 有循循善诱的感觉
传送门
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现