【拓展欧几里得】POJ-1061 青蛙的约会

上链接:1061 -- 青蛙的约会

题意

两只青蛙在循环坐标轴上朝着同一方向跳跃,其中两只青蛙的起始位置和单次跳跃距离给定,以及坐标轴的长度给定,求使得两只青蛙相遇的跳跃次数。

分析

坐标轴,跳跃,模拟!NO!不可能!

数学题嘛...起始位置分别为x和y,单次跳跃距离分别为m,n,一条坐标轴的长度为L,把这条循环的坐标轴看成无限延伸的,长度为L的倍数的坐标轴,很容易想到以下表达式

设青蛙A的起始坐标为x,单次跳跃距离为m,B青蛙起始坐标为y,单次跳跃距离为n,则有

\left ( x+pa \right )-\left ( y+pb \right )=qL   【1】,其中p代表跳跃的次数

可以证明,在两只青蛙跳跃间距出现L的整数倍数时(在无限坐标轴上),在循环坐标轴上即为相遇。

对于上式,x,y,a,b,L皆为已知量,p,q为变量,故可稍化简该式子,得到:

\left ( n-m \right )p+Lq=x-y  【2】

观察式子,很容易看到这是标准的二元一次方程ax+by=n的形式,若方程【2】存在整数解,青蛙就有可能相遇,同时本题要求的是p的最小整数解

至于如何判断ax+by=n形式的二元一次方程是否有解,在有解的情况下如何求解,求出解之后如何得到最小正整数解,考虑拓展欧几里得算法

拓展欧几里得

对于方程二元一次方程ax+by=n,有解的充要条件是gcd(a,b)可以整除n。

稍作解释即:令a=gcd(a,b)a',b=gcd(a,b)b',有ax+by=gcd(a,b)(a'x+b'y)=n,如果x,y,a',b'都是整数,那么c必须是gcd(a,b)的倍数才能使得方程有解

在有解的情况下,若能够确定该方程的一个特解(x0,y0),那么则能够求得通解,在此不做赘述,对于最小非负整数解则有:

x_0'=(x_0\%\frac{b}{gcd(a,b)}+\frac{b}{gcd(a,b)})\%\frac{b}{gcd(a,b)}

y_0'=(y_0\%\frac{a}{gcd(a,b)}+\frac{a}{gcd(a,b)})\%\frac{a}{gcd(a,b)}

那么如何求这个特解(x0,y0)呢?

引入拓展欧几里得算法

当方程符合ax+by=gcd(a,b)时,可用拓展欧几里得求得特解(x0,y0),代码如下

ll exgcd(ll a,ll b,ll &x,ll &y) {
	if(b==0) {
		x=1;
		y=0;
		return a;
	} 
	ans=exgcd(b,a%b,x,y);
	ll tmp=x;
	x=y;
	y=tmp-(a/b)*y;
	return ans;
    //顺便返回a,b的公约数
} 

但这仅求得的是方程ax+by=gcd(a,b)的一个特解,而非我们所要的ax+by=n的特解

由于方程满足gcd(a,b)可以整除n,则可将方程两边共乘n/gcd(a,b),得到以下式子

\frac{ax_0n}{gcd(a,b)}+\frac{by_0n}{gcd(a,b)}=n

故可知,若求得方程ax+by=gcd(a,b)的特解为(x0,y0),则对应的ax+by=n方程的特解就在原特解上乘上对应的系数n/gcd(a,b)即可。

随后可根据题目要求套之前的求最小非负整数解的公式。

提示

本题中容易出错的是,保证方程求得非负解,要求a>=0,即n-m>=0,故应当注意在输出之后处理系数。

代码如下

#include<iostream> 
using namespace std;
typedef long long ll;
ll ans;
ll exgcd(ll a,ll b,ll &x,ll &y) {
	if(b==0) {
		x=1;
		y=0;
		return a;
	} 
	ans=exgcd(b,a%b,x,y);
	ll tmp=x;
	x=y;
	y=tmp-(a/b)*y;
	return ans;
} 
int main() {
	ios::sync_with_stdio(false);
	ll x,y,n,m,l;
	cin>>x>>y>>m>>n>>l;
	ll a=n-m,b=l,c=x-y;
	if(a<0) {
		a=-a;
		c=-c;
	}
	ll x0,y0;
	exgcd(a,b,x0,y0);
	ll g=ans;
	if(c%g) {
		cout<<"Impossible\n";
	}else {
		ll u=((x0*(c/g))%(b/g)+(b/g))%(b/g);
		cout<<u<<endl;
	}
}

学习笔记。。没有严谨的证明,套路向

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值