POJ 1061 青蛙的约会
2014-07-23 21:29
218 查看
/*题意
A青蛙一开始在x位置,B青蛙在y位置。A青蛙每次跳m米,B青蛙每次跳n米,
并且都是向右跳的,地球纬线长度是L,地球是圆的,两只青蛙每次跳跃用时相等。
A青蛙想追B青蛙,问多少次后它们能跳到一起。如果它们永远不能相遇,就输出Impossible
*/
/*定理
定理一:如果d = gcd(a, b),则必能找到正的或负的整数k和l,使d = a*k + b*l
定理二:若gcd(a, b) = 1,则方程ax ≡ c (mod b)在[0, b-1]上有唯一解。
定理三:若gcd(a, b) = d,则方程ax ≡ c (mod b)在[0, b/d - 1]上有唯一解。
*/
/*分析
这道题本质上是求一个同余方程,我们设两只青蛙要跳t次,也就是用时为t个单位
本质上如果可以在一起的话会存在一个整数k(可正可负可为0),使两者的末坐标相差kL,这时两者是在同一点
这里有(x+t*m)-(y+t*n)=k*L,即x+tm≡y+tn(mod L)
上面的第一个式子可以化为(m-n)t-Lk=y-x的形式,这就是ax + by = c,求整数x的模型。
要求ax + by = c的整数x解,可不是那么简单滴
首先,设d = gcd(a, b),方程两边除以d得到a/d * x + b/d * y = c/d
a是整除d的,b也是整除d的,而x、y都是整数解,所以要求c/d也是整数。如果c不整除d,则Impossible
如果我们能求出ax0+by0=d的解x0和y0,那么两边乘以c/d即a(c/d * x0) + b(c/d * y0) = c,
就可以得到原来方程的解x = (c/d * x0),y = (c/d * y0)
而对于x0和y0我们可以利用拓展欧几里得算法得到
然后由x = (c/d * x0)我们就可以得到一个特解x,但是实际上我们只是计算出来了一个x的特例,实际上有无数个x解
为什么这么说呢,
如果我得到一个特解x*,那么加上若干倍b还是这个方程的解,因为a(x*+k*b) = ax* + a*k*b ≡ c + 0 ≡ c (mod b)。
因而方程在[0, b-1]上一定有整数解(假如小于0,你加上若干倍b,就可以让它保持在0~b-1中;
如果大于b-1,你减去若干倍b,它也保持0~b-1)。
那么怎样求最小的非负整数x呢?又要用到两个定理:
定理二:若gcd(a, b) = 1,则方程ax ≡ c (mod b)在[0, b-1]上有唯一解。
定理三:若gcd(a, b) = d,则方程ax ≡ c (mod b)在[0, b/d - 1]上有唯一解。
如果得到ax ≡ c (mod b)的某一特解X,那么我令r = b/gcd(a, b),可知x在[0, r-1]上有唯一解,
所以我用x = (X % r + r) % r就可以求出最小非负整数解x了!
再多说一句,这道题要用long long
*/
#include<iostream>
using namespace std;
long long int x,y,m,n,L,t;//这六个量依次为A、B的始点,A、B的跳距,周长,所求的跳的次数
int main()
{
void ex_gcd(long long int a,long long int b,long long int& d,long long int& x,long long int& y);
long long int a,b,c,d,x0,y0,r;
while(cin>>x>>y>>m>>n>>L)
{
a=m-n;b=-L;c=y-x;
ex_gcd(a,b,d,x0,y0);
r=b/d;
if(c%d==0)
{
t=c/d*x0;/*此步是求特解t*/
t=(t%r+r)%r;
cout<<t<<endl;
}
else{cout<<"Impossible"<<endl;}
}
return 0;
}
/*已知整数a、b,扩展欧几里得算法可以在求得a、b的最大公约数的同时,
能找到整数x、y(其中一个很可能是负数),
使它们满足贝祖等式ax + by = \gcd(a, b).*/
void ex_gcd(long long int a,long long int b,long long int& d,long long int& x,long long int& y)
{
if(b==0){d=a;x=1;y=0;}
else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}
}
A青蛙一开始在x位置,B青蛙在y位置。A青蛙每次跳m米,B青蛙每次跳n米,
并且都是向右跳的,地球纬线长度是L,地球是圆的,两只青蛙每次跳跃用时相等。
A青蛙想追B青蛙,问多少次后它们能跳到一起。如果它们永远不能相遇,就输出Impossible
*/
/*定理
定理一:如果d = gcd(a, b),则必能找到正的或负的整数k和l,使d = a*k + b*l
定理二:若gcd(a, b) = 1,则方程ax ≡ c (mod b)在[0, b-1]上有唯一解。
定理三:若gcd(a, b) = d,则方程ax ≡ c (mod b)在[0, b/d - 1]上有唯一解。
*/
/*分析
这道题本质上是求一个同余方程,我们设两只青蛙要跳t次,也就是用时为t个单位
本质上如果可以在一起的话会存在一个整数k(可正可负可为0),使两者的末坐标相差kL,这时两者是在同一点
这里有(x+t*m)-(y+t*n)=k*L,即x+tm≡y+tn(mod L)
上面的第一个式子可以化为(m-n)t-Lk=y-x的形式,这就是ax + by = c,求整数x的模型。
要求ax + by = c的整数x解,可不是那么简单滴
首先,设d = gcd(a, b),方程两边除以d得到a/d * x + b/d * y = c/d
a是整除d的,b也是整除d的,而x、y都是整数解,所以要求c/d也是整数。如果c不整除d,则Impossible
如果我们能求出ax0+by0=d的解x0和y0,那么两边乘以c/d即a(c/d * x0) + b(c/d * y0) = c,
就可以得到原来方程的解x = (c/d * x0),y = (c/d * y0)
而对于x0和y0我们可以利用拓展欧几里得算法得到
然后由x = (c/d * x0)我们就可以得到一个特解x,但是实际上我们只是计算出来了一个x的特例,实际上有无数个x解
为什么这么说呢,
如果我得到一个特解x*,那么加上若干倍b还是这个方程的解,因为a(x*+k*b) = ax* + a*k*b ≡ c + 0 ≡ c (mod b)。
因而方程在[0, b-1]上一定有整数解(假如小于0,你加上若干倍b,就可以让它保持在0~b-1中;
如果大于b-1,你减去若干倍b,它也保持0~b-1)。
那么怎样求最小的非负整数x呢?又要用到两个定理:
定理二:若gcd(a, b) = 1,则方程ax ≡ c (mod b)在[0, b-1]上有唯一解。
定理三:若gcd(a, b) = d,则方程ax ≡ c (mod b)在[0, b/d - 1]上有唯一解。
如果得到ax ≡ c (mod b)的某一特解X,那么我令r = b/gcd(a, b),可知x在[0, r-1]上有唯一解,
所以我用x = (X % r + r) % r就可以求出最小非负整数解x了!
再多说一句,这道题要用long long
*/
#include<iostream>
using namespace std;
long long int x,y,m,n,L,t;//这六个量依次为A、B的始点,A、B的跳距,周长,所求的跳的次数
int main()
{
void ex_gcd(long long int a,long long int b,long long int& d,long long int& x,long long int& y);
long long int a,b,c,d,x0,y0,r;
while(cin>>x>>y>>m>>n>>L)
{
a=m-n;b=-L;c=y-x;
ex_gcd(a,b,d,x0,y0);
r=b/d;
if(c%d==0)
{
t=c/d*x0;/*此步是求特解t*/
t=(t%r+r)%r;
cout<<t<<endl;
}
else{cout<<"Impossible"<<endl;}
}
return 0;
}
/*已知整数a、b,扩展欧几里得算法可以在求得a、b的最大公约数的同时,
能找到整数x、y(其中一个很可能是负数),
使它们满足贝祖等式ax + by = \gcd(a, b).*/
void ex_gcd(long long int a,long long int b,long long int& d,long long int& x,long long int& y)
{
if(b==0){d=a;x=1;y=0;}
else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}
}
相关文章推荐
- poj-1061 青蛙的约会
- POJ - 1061 青蛙的约会(拓展GCD
- poj 1061 青蛙约会
- poj1061-青蛙的约会(扩展欧几里德算法)
- POJ1061 青蛙的约会(数论 扩展欧几里得算法)
- POJ 1061 青蛙的约会
- poj1061青蛙的约会
- POJ-1061 青蛙的约会-数论扩展欧几里德算法入门及推导
- POJ 1061 青蛙约会
- POJ 1061 青蛙的约会
- POJ-1061 青蛙的约会
- poj 1061 青蛙的约会(扩展gcd)
- POJ 1061 青蛙的约会(一元线性同余方程)
- POJ 1061 青蛙的约会【拓展欧几里得】
- 青蛙的约会 POJ - 1061 拓展欧几里得
- POJ 1061 青蛙的约会 (扩展欧几里德解不定方程)
- 青蛙的约会(poj1061+欧几里德+同余方程)
- poj 1061青蛙的约会
- poj 1061 青蛙的约会(扩展欧几里得)
- POJ-1061 青蛙的约会 扩展GCD