POJ 1061 青蛙的约会 (扩展欧几里得)

青蛙的约会
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 97673 Accepted: 18409

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

1 2 3 4 5

Sample Output

4
题意,求解最少的时间,让得两个青蛙可以相遇。
这道题目涉及的扩展欧几里得知识,请读者自行补脑,这里只说明为什么可以用扩展欧几里得以及怎么用扩展欧几里得去算出结果
有题目可以列出方程式:
(x + m * t) % L - (y + n * t) % L == 0
如此可以写成 x - y + (m - n) * t == p * L,如果青蛙A与青蛙B在相同时间内行驶的距离的差为L的倍数,那么他们能够相遇
接着运用扩展欧几里得求解他们一个整数解
a = (m - n)
b = L
void gcd(LL a,LL b,LL &d, LL &x, LL &y){
    if(!b){
        d = a;
        x = 1;
        y = 0;
    }
    else{
        gcd(b,a % b, d, y, x);
        y -= x * (a / b);
    }
}
其中d为最大公约数
于是如果(x - y) 不是最大公约数的倍数,证明没有整数解(理由,请自行看扩展欧几里得的知识点)
接着是求解最小的t,很明显
有扩展欧几里得可以知道
此时求解的X,Y并非整数解而是方程
{x - y + (m - n) * t == p * L} -> {(n - m) * t + p * L == x - y} -> {(n - m) * t + p * L == gcd(n - m, p)的解}
所以我们还要将它转换为整数解进行求值(此处的求解属于扩展欧几里得范畴)
t =X * (x - y) / d即为答案,但是这里要注意就是会出现负数的情况
所以公式进行优化
令n - m = a,L = b,x - y = d
X = t0,Y = p0,
那么{(n - m) * t + p * L == x - y} -> {a * t0 + b * p0 == d}
那么正解为a * t0 * d / gcd + b * p0 * d / gcd == d
由于出现负数情况:a * (t0 * d / gcd + b * k) + b * (p0 * d / gcd - a * k) == d
所以我们求解的t其实是t0 * d / gcd + b * k(k为任意整数)所以对b即L进行取余
所以t = ((t + L) % L + L) % L
 

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;


void gcd(LL a,LL b,LL &d, LL &x, LL &y){
    if(!b){
        d = a;
        x = 1;
        y = 0;
    }
    else{
        gcd(b,a % b, d, y, x);
        y -= x * (a / b);
    }
}
int x, y, m, n, L;
int main(){
    while(~ scanf("%I64d%I64d%I64d%I64d%I64d",&x, &y, &m, &n, &L)){
        LL d,X,Y;
        gcd(m - n, L, d, X, Y);
        if((y - x) % d!= 0){
            printf("Impossible\n");
        }
        else{
            X *= (x - y) / d;
            X =((L - X) % L + L) % L;
            printf("%I64d\n",X);
        }
    }
    return 0;
}
同类型题目:

背景

康熙是中国历史乃至世界历史中最伟大的帝王之一,清除螯拜,撤除三藩,统一台湾,平定准葛尔叛乱;与此同时,出众的他也被世界各国遣清使臣所折服。康熙是历史上少有的全人,不仅文武兼得,而且在各各方面都有见地,比如说航海、数学、英语、构图、建筑等等。一个最好的例子可以证明:康熙当年演算代数题的草稿纸至今仍然保存完好。

话说康熙掌权之后,每天都抽空做数学题,特别是无聊题。这些天,某某老师开始教他做一些奇怪的题目。在第一节课的时候,老师就问了康熙一个超BT的题目:

描述

话说西汉时期,汉武帝刘彻派遣张骞出使西域,欲同月氏国结交而共驱匈奴。同时,月氏国也欲同大汉结交,也派出使者康破伦出使大汉,可是因为月氏国对于大汉的认知甚少,康破伦同样向西出使大汉。一开始,张骞从大汉出发,康破伦从月氏国出发,两人都在同一纬度线上,张骞所处的经度为x,康破伦所处的经度为y;接下来,两人同时向西走,而且只能向西走,张骞每天走m公里,康破伦每天走n公里,且每天走路的速度不变,也不停下来休息;这样两人就在这一条长为L的纬度线上一直向西走。问:过了多少天之后张骞和康破伦会碰面,并磋商两国结交之事(所谓碰面,是指两人处在同一经度上)。

这下,康熙犯难了,他还是个不大的青年,怎么可能做得出这么难的题目;但是,他又是统领全国的帝皇,怎么能在老师面前丢这么大一个面子。康熙想:不行!一定得把这个题做出来!(然后就有了下面这段记录)
第一天,……
第二天,…………
第三天,………………
第四天,……………………
第五天,…………………………
第六天,………………………………
第七天,……………………………………!!!!!!!
啊!第七天,康熙终于打了7个感叹号,得出了一个重要的结论!!!!!那就是——做不出来。(汗),没办法,他只有请教你,他的挚友,帮他解决这一难题。康熙答应你,如果你把这一题做出来了,你将得到御赐赏银一万万mod1两!$$$$$$$$-$$$$$$$$。为了改变你生活的现状——衣衫褴褛、闻鼠起舞、蟑螂为伴,你下定了决心——我一定得把这题解决!

格式

输入格式

输入只包括一行5个整数x,y,m,n,L
其中0<x≠y < =2000000000,0 < m、n < =2000000000,0 < L < =2100000000。

输出格式

输出碰面所需要的天数,如果永远不可能碰面则输出一行"Impossible"。

样例1

样例输入1[复制]

1 2 3 4 5

样例输出1[复制]

4
这道题目中我得到了启示,我之前的推理可能有点问题,因为同样的代码在这里无法通过,所以,提供python正确的代码
C++代码,提供以为大神的地址:http://blog.csdn.net/qwb492859377/article/details/47679225
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

def gcd(a, b):
    if not b:
        return a, 1, 0
    else:
        g, x, y = gcd(b, a % b)
        return g, y, x - y * (a / b)
def solve(a, b, c, d):
    G, X, Y = gcd(a, b)
    if c % G:
        return False, 0
    X = X * c / G
    t0 = (d - X) * G / b
    t = X + b / G * t0
    if t < d:
        t0 = t0 + 1
        t = X + b / G * t0
    return True, t
import sys
import math
for line in sys.stdin:
    x, y, m, n, L = map(long, line.split())
    P = False
    if n - m > 0:
        P, t = solve(n - m, L, x - y, 0)
    elif n - m < 0:
        P, t = solve(m - n, L, y - x, 0)
    if not P or n - m == 0:
        print 'Impossible'
    else :
        print t

    


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值