poj1061-青蛙的约会
2016-07-17 16:11
225 查看
Description
两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。
Input
输入只包括一行5个整数x,y,m,n,L,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < L < 2100000000。
Output
输出碰面所需要的跳跃次数,如果永远不可能碰面则输出一行"Impossible"
Sample Input
Sample Output
代码实现:
#include<iostream>
#include<cstdio>
#define LL __int64
using namespace std;
LL X,Y;
LL gcd(LL a,LL b)//欧几里得,求两个数的最大公约数
{
return b?gcd(b,a%b):a;
}
void exgcd(LL a,LL b)//扩展欧几里得
{
if(b==0)
{
X=1,Y=0;
return ;
}
exgcd(b,a%b);
int t=X;X=Y;Y=t-a/b*Y;
return ;
}
int main()
{
LL x,y,n,m,l,a,c,d;
while(cin>>x>>y>>m>>n>>l)
{
a=n-m;
c=x-y;
d=gcd(a,l);
if(c%d)
{
cout<<"Impossible\n";
continue;
}
c/=d;
exgcd(a,l);
X*=c;
LL t=X%(l*d);
while(t<0)
{
t+=(l*d);
}
cout<<t<<endl;
}
return 0;
}
欧几里得与扩展欧几里得的知识详见 百度百科 扩展欧几里得
这个题目转换成数学公式为:(x+mt)-(y+nt)=kl A,B相遇时,A走的路程与B走的路程相差整个圈的长度的整数倍,求解t,t为跳跃的次数
(n-m)t+kl=x-y
a=n-m b=l c=x-y
ax+by=c(t=x,k=y)
如果c为a,b的最大公约数整数倍,此方程有整数解,否则没有整数解,有解时:
d=gcd(a,b) k=c/d
a(x/k)+b(y/k)=c/k
a(x/k)+b(y/k)=gcd(a,b) l与b相等
用exgcd(a,l)求出整数解X X=x0/k x0=Xk
其他整数解:
x=x0+bdt
y=y0-adt
x0%=bd//当x0大于0时,可以使x0成为最小正整数解,当x0小于0时,可以使x0尽快加成最小正整数解
另一种解法:
#include<iostream>
#include<cstdio>
#define LL __int64
using namespace std;
LL X,Y;
LL gcd(LL a,LL b)
{
return b?gcd(b,a%b):a;
}
void exgcd(LL a,LL b)
{
if(b==0)
{
X=1,Y=0;
return ;
}
exgcd(b,a%b);
int t=X;X=Y;Y=t-a/b*Y;
return ;
}
int main()
{
LL x,y,n,m,l,a,c,d;
while(cin>>x>>y>>m>>n>>l)
{
a=n-m;
c=x-y;
d=gcd(a,l);
if(c%d)
{
cout<<"Impossible\n";
continue;
}
a/=d,l/=d,c/=d;
exgcd(a,l);
X*=c;
LL t=X%l;
while(t<0)
{
t+=l;
}
cout<<t<<endl;
}
return 0;
}
a/=d,l/=d这一步使a,b的最大公约数为1
(a/d)x+(b/d)y=c/d=k
(a/d)(x/k)+(b/d)(y/k)=1
A(x/k)+B(y/k)=1
两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。
Input
输入只包括一行5个整数x,y,m,n,L,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < L < 2100000000。
Output
输出碰面所需要的跳跃次数,如果永远不可能碰面则输出一行"Impossible"
Sample Input
1 2 3 4 5
Sample Output
4
代码实现:
#include<iostream>
#include<cstdio>
#define LL __int64
using namespace std;
LL X,Y;
LL gcd(LL a,LL b)//欧几里得,求两个数的最大公约数
{
return b?gcd(b,a%b):a;
}
void exgcd(LL a,LL b)//扩展欧几里得
{
if(b==0)
{
X=1,Y=0;
return ;
}
exgcd(b,a%b);
int t=X;X=Y;Y=t-a/b*Y;
return ;
}
int main()
{
LL x,y,n,m,l,a,c,d;
while(cin>>x>>y>>m>>n>>l)
{
a=n-m;
c=x-y;
d=gcd(a,l);
if(c%d)
{
cout<<"Impossible\n";
continue;
}
c/=d;
exgcd(a,l);
X*=c;
LL t=X%(l*d);
while(t<0)
{
t+=(l*d);
}
cout<<t<<endl;
}
return 0;
}
欧几里得与扩展欧几里得的知识详见 百度百科 扩展欧几里得
这个题目转换成数学公式为:(x+mt)-(y+nt)=kl A,B相遇时,A走的路程与B走的路程相差整个圈的长度的整数倍,求解t,t为跳跃的次数
(n-m)t+kl=x-y
a=n-m b=l c=x-y
ax+by=c(t=x,k=y)
如果c为a,b的最大公约数整数倍,此方程有整数解,否则没有整数解,有解时:
d=gcd(a,b) k=c/d
a(x/k)+b(y/k)=c/k
a(x/k)+b(y/k)=gcd(a,b) l与b相等
用exgcd(a,l)求出整数解X X=x0/k x0=Xk
其他整数解:
x=x0+bdt
y=y0-adt
x0%=bd//当x0大于0时,可以使x0成为最小正整数解,当x0小于0时,可以使x0尽快加成最小正整数解
另一种解法:
#include<iostream>
#include<cstdio>
#define LL __int64
using namespace std;
LL X,Y;
LL gcd(LL a,LL b)
{
return b?gcd(b,a%b):a;
}
void exgcd(LL a,LL b)
{
if(b==0)
{
X=1,Y=0;
return ;
}
exgcd(b,a%b);
int t=X;X=Y;Y=t-a/b*Y;
return ;
}
int main()
{
LL x,y,n,m,l,a,c,d;
while(cin>>x>>y>>m>>n>>l)
{
a=n-m;
c=x-y;
d=gcd(a,l);
if(c%d)
{
cout<<"Impossible\n";
continue;
}
a/=d,l/=d,c/=d;
exgcd(a,l);
X*=c;
LL t=X%l;
while(t<0)
{
t+=l;
}
cout<<t<<endl;
}
return 0;
}
a/=d,l/=d这一步使a,b的最大公约数为1
(a/d)x+(b/d)y=c/d=k
(a/d)(x/k)+(b/d)(y/k)=1
A(x/k)+B(y/k)=1
相关文章推荐
- Base64
- 26 复杂链表的复制
- Java Arrays类进行数组排序
- 二叉树非递归求深度和节点个数
- 冒泡排序
- 【linux c】什么是野指针以及如何避免野指针_学习笔记_010
- Android自定义捕获Application全局异常
- 踩水
- 【转载】.NET/C#-uploadify视频文件or大文件上传
- IntelliJ IDEA Maven 安装配置
- 设计模式---结构类型---装饰
- 参考韩顺平老师的视频,用HTML写一个静态网页的邮箱
- addWidget的参数说明
- 【NOIP2016提高A组模拟7.17】锦标赛
- 天热无聊,用C语言函数指针实现的小函数^_^
- Eclipse之安装及汉化步骤
- Android开发——获取应用数据/缓存大小并清理缓存
- 内存按字节编址,地址区间为[90000H,CFFFFH],若用32K*8bit的存储器芯片构成该内存,需要__块
- C++ read函数读入int整形数据
- Android开发——获取应用数据/缓存大小并清理缓存