POJ-1061 青蛙的约会---扩展欧几里得算法
Posted 努力努力再努力x
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ-1061 青蛙的约会---扩展欧几里得算法相关的知识,希望对你有一定的参考价值。
题目链接:
https://cn.vjudge.net/problem/POJ-1061
题目大意:
两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。
解题思路:
假设t时刻相遇
有:(x + mt) = (y + nt) (mod L)
也就是 x + mt - y - nt = K * L
(m - n) * t + K * L = y - x
(因为K取任意整数,移到方程左端可以不管他的正负,反正对求出的K不处理)
也就是:a * t + b * K = y - x a = m - n b = L 求解t和K
特判 a = 0 的时候 x = y解为0,反之无解
当a < 0时,标记一下,然后a取正数,最后求出的t再取一下相反数即可
对于ax + by = c的求解
先求解ax + by = gcd(a, b) 求出x0,y0
如果gcd(x, y)整除c则有解,反之无解
根据x0 y0可得到一解:
x1 = x0 * c / gcd(a, b)
y1 = y0 * c / gcd(a, b)
所有解:
x = x1 + b / gcd(a, b) * t
y = y1 + a / gcd(a, b) * t
最小正数x的解
b` = b / gcd(a, b)
a` = a / gcd(a, b)
x2 = ((x1 % b`) + b`) % b`
y2 根据x2计算出来
同理可求出最小正数y的解
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 using namespace std; 5 typedef long long ll; 6 ll extgcd(ll a, ll b, ll&x, ll&y)//ax+by = gcd(a, b)的解。返回值为gcd 7 { 8 ll d = a; 9 if(b) 10 { 11 d = extgcd(b, a % b, y, x); 12 y -= (a / b) * x; 13 } 14 else x = 1, y = 0; 15 return d; 16 } 17 int main() 18 { 19 ll x, y, m, n, l; 20 cin >> x >> y >> m >> n >> l; 21 ll xx, yy; 22 ll a = m - n, b = l; 23 if(a == 0) 24 { 25 if(x == y)cout<<"0"<<endl; 26 else cout<<"Impossible"<<endl; 27 return 0; 28 } 29 bool flag = 0; 30 if(a < 0)a = -a, flag = 1; 31 ll g = extgcd(a, b, xx, yy); 32 if((y - x) % g)cout<<"Impossible"<<endl; 33 else 34 { 35 xx = xx * (y - x) / g; 36 if(flag)xx = -xx; 37 l = l / g; 38 xx = ((xx % l) + l) % l; 39 cout<<xx<<endl; 40 } 41 return 0; 42 }
以上是关于POJ-1061 青蛙的约会---扩展欧几里得算法的主要内容,如果未能解决你的问题,请参考以下文章