【原创】用拓展欧几里得解不定方程 ※POJ-1061-青蛙的约会

很早很早以前(寒假),学习了拓展欧几里得,知道如何用拓欧解不定方程。现在(暑假),我们来刷几道题。

青蛙的约会

题目描述

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

题目大意

大家看得懂中文吧!我就不说了QωQ

题目分析

首先,我们可以轻松的列出方程:
设走了t步,x,y,m,n,L含义如题。
x+m*t≡y+n*t (mod L)
移项:(x-y)+t(m-n)≡0(mod L)
这个式子等价于(x-y)+t(m-n)=kL
//t和k才是未知数

再移项:kL-t(m-n)=(x-y)
为了化出不定方程的标准形式(不化也可以),再改成:
kL+t(n-m)=(x-y)
n-m=p,x-y=q
kL+tp=q
//再次重申,t和k才是未知数!
上式已经是标准的不定方程了,然后怎么解它呢?

以下是重点
首先,它有解的前提是gcd(L,p)|q。(整除符号,不是或运算(QωQ))
所以我们先求gcd(L,p)。做一次拓欧,求出gcd(L,p),同时我们求出了(拓欧的)x0,y0先放着。(为了不和题目的x,y冲突)
接着,如果gcd(L,p)不整除q,那么之后无法做下去了,此题无解。
这里写图片描述

代码

#include<iostream>
#include<cstdio>
using namespace std;
long long va,vb,ba,bb,m,n,l,k,t,d,x,y;
long long gcd(long long a,long long b,long long &x,long long &y)
{
    if(!b)
    {
        x=1; y=0;
        return a;
    }
    long long w=gcd(b,a%b,y,x);
    y-=x*(a/b);
    return w;
}
int main()
{
    cin>>ba>>bb>>va>>vb>>l;
    m=va-vb; n=bb-ba;
    d=gcd(m,l,x,y);
    if(n%d!=0) 
    {
        puts("Impossible");
        return 0;
    }
    t=l/d;
    k=(x*(n/d)%t+t)%t;
    if(k<0) k+=l;
    cout<<k<<endl;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值