青蛙的约会

Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u

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
首先介绍下什么是扩展欧几里得

扩展欧几里德算法

基本算法:对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。

证明:设 a>b。

  1,显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;

  2,ab!=0 时

  设 ax1+by1=gcd(a,b);

  bx2+(a mod b)y2=gcd(b,a mod b);

  根据朴素的欧几里德原理有 gcd(a,b)=gcd(b,a mod b);

  则:ax1+by1=bx2+(a mod b)y2;

  即:ax1+by1=bx2+(a-(a/b)*b)y2=ay2+bx2-(a/b)*by2;

  根据恒等定理得:x1=y2; y1=x2-(a/b)*y2;

这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2.

   上面的思想是以递归定义的,因为 gcd 不断的递归求解一定会有个时候 b=0,所以递归可以结束。

题意:公青蛙一开始在x位置,母青蛙在y位置。公青蛙每次跳m米,母青蛙每次跳n米,并且都是向右跳的。地球经线长度是L,然后地球是圆的,也就是说,跳到L、L+1、L+2……其实就是跳到0、1、2。 公青蛙想追母青蛙,问多少次后它们能跳到一起。如果它们永远不能相遇,就输出Impossible。

题解:就是求一个k,使x + k*m ≡ y + k*n (mod L) ,然后对方程化简,就变成(n-m) * k ≡ x-y (mod L)。然后这个方程其实就等价于(n-m)*k + L*s = x-y。这就是ax + by = c求整数x的模型。

要求ax + by = c的整数x解。(n-m)*t+L*S=x-y。首先,设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 * (c / d)是最小的解,但有可能是负数。

因为a * ( x0 *(c / d) + b*n) + b * (y0 * (c / d ) – a*n) = c; (n是自然数)

所以解为 (x0 * (c / d) % b + b) % b;

#include <iostream>
using namespace std;
typedef long long ll;
void gcd(ll a,ll b,ll &d,ll &x,ll &y)
{
if(!b) {d=a;x=;y=;}
else {gcd(b,a%b,d,y,x);y-=x*(a/b);}
}
int main()
{
ll x,y,m,n,L,X,Y,d,r;
while(cin>>x>>y>>m>>n>>L)
{
//求x
ll a=m-n,b=-L,c=y-x; //要求ax+by=c; 最开始先构造 aX+bX=gcd(a,b)=d; (a/d)*X+(b/d)*X=1;
// a*(c/d)*X+b*(c/d)*X=c;
// 即 x=(c/d)*X; 注意x不一定是最小正整数解
// 用公式a(x+b*n)+b(y-a*n)=c;对x进行优化
// 那么这里的b是什么呢
gcd(a,b,d,X,Y);
if(c%d) //这里要注意问题的实际意义 ab能除开d是一定的也是没用的 c必须能除开d才可以
//c要是除不开d就不可能相遇 能除开就把abc都除d
cout<<"Impossible"<<endl;
else
{
a=a/d;
b=b/d;
//关于为什么要将b除以d
//这里要深刻理解最大公约数的意义
//假设gcd(15,9)=3; a=5,b=3,a变化b次可以遍历所有情况
//同理b变化a次可以遍历所有情况 求ax的x 把x对b取余即可遍历所有情况。
//这个数据的a的情况无非 5 10 15 三种。即b=3。
//如果不用新的b 就会多循环 b-b/gcd(a,b)次 不是最小的解
//比如 15 9 就会多遍历6次
// 9x+24y=3; x=-5,y=2; b=24的时候x优化成x=19 y=2-9=-7
// 3x+8y=1; b=8的时候x优化成x=3 y优化成 y=2-3=-1
//也就是说b=24不能遍历所有情况 可能会跳过最优解
//比如100x+200y=500; 答案显然是x取任意奇数 最小正整数解x=1; 而y=(5-x)/2;
//如果x取-1 算结果的时候用b=200取余 x=199 很明显不是最小正整数解
//是错误的 即不能遍历所有奇数情况 应该化为x+2y=5; b=2; x=1;为正解。
//实际上这里的新的ab 已经不是原来的意义了
//原a=a0 b=b0 新a=a1 b=b1
//a0*b1=b0*a1 遍历所有情况 a1 b1实际上是查数用的
c=c/d;
cout<<(X*c%b+b)%b<<endl;
}
}
return ;
}

poj 1061 青蛙的约会 (扩展欧几里得模板)的更多相关文章

  1. poj 1061 青蛙的约会 拓展欧几里得模板

    // poj 1061 青蛙的约会 拓展欧几里得模板 // 注意进行exgcd时,保证a,b是正数,最后的答案如果是负数,要加上一个膜 #include <cstdio> #include ...

  2. POJ 1061 青蛙的约会 扩展欧几里得

    扩展欧几里得模板套一下就A了,不过要注意刚好整除的时候,代码中有注释 #include <iostream> #include <cstdio> #include <cs ...

  3. Poj 1061 青蛙的约会(扩展欧几里得解线性同余式)

    一.Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要 ...

  4. POJ - 1061 青蛙的约会 扩展欧几里得 + (贝祖公式)最小正整数解

    题意: 青蛙 A 和 青蛙 B ,在同一纬度按照相同方向跳跃相同步数,A的起点为X ,每一步距离为m,B的起点为Y,每一步距离为 n,一圈的长度为L,求最小跳跃步数. 思路: 一开始按照追击问题来写, ...

  5. POJ.1061 青蛙的约会 (拓展欧几里得)

    POJ.1061 青蛙的约会 (拓展欧几里得) 题意分析 我们设两只小青蛙每只都跳了X次,由于他们相遇,可以得出他们同余,则有: 代码总览 #include <iostream> #inc ...

  6. poj 1061 青蛙的约会+拓展欧几里得+题解

    青蛙的约会+拓展欧几里得+题解 纵有疾风起 题意 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出 ...

  7. pku 1061 青蛙的约会 扩展欧几里得

    青蛙的约会Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 120482 Accepted: 25449Description 两只青 ...

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

    题意:已知青蛙1位置x,速度m,青蛙2位置y,速度n,纬线长度为l,求他们相遇时最少跳跃次数. 思路:设最小跳跃次数为k,则(x + k*m) - (y + k*n) = q*l:经过整理得到k*(n ...

  9. [poj1061]青蛙的约会<扩展欧几里得>

    题目链接:http://poj.org/problem?id=1061 其实欧几里得我一直都知道,只是扩展欧几里得有点蒙,所以写了一道扩展欧几里得裸题. 欧几里得算法就是辗转相除法,求两个数的最大公约 ...

随机推荐

  1. thinkphp3.2 where 条件查询 复查的查询语句

    复查的查询语句 有的时候,我们希望通过一次的查询就能解决问题,这个时候查询条件往往比较复杂,但是却比多次查询库来的高效. 实在是搞不定的话就直接用$where[‘_string’] = ‘xxxx’, ...

  2. 生产-消费模式的synchronized和lock实现(十)

    lock: package com.net.thread.lock; import java.util.concurrent.locks.Condition; import java.util.con ...

  3. iOS-UICollectionViewController 介绍

    废话不多说,列几个列子 (几种情况下的做法): 情景一: 介绍:1. 在UIViewController 上加 UICollectionView (用代码 创建 UICollectionView). ...

  4. 010---Django的模型层(2)

    确定模型关系: ''' Publish ---- Book 多对一:一个出版社对应多本书,在多的那张表添加关联字段 Book ---- Author 多对多:一个书对应多个作者,多个作者对应一本书 会 ...

  5. dubbo的rpc异常

    Exception in thread "main" com.alibaba.dubbo.rpc.RpcException: Failed to invoke the method ...

  6. PHP.TP框架下商品项目的优化1-时间插件、鼠标所在行高亮、布局规划页面

    1.优化搜索表单中按时间搜索的功能 添加一个时间插件datetimepicker,在lst.html中,注意要导入jquery.min.js,此处从前文的在线编辑器中导入 <!-- 导入 --& ...

  7. Kafka安装和常用操作命令

    Kafka安装: 下载kafka_2.10-0.8.2.1 1.关闭防火墙 2.修改配置文件  server.properties broker.id=1log.dirs= /usr/kafka_2. ...

  8. Android学习记录(5)—在java中学习多线程下载之断点续传②

    在上一节中我们学习了在java中学习多线程下载的基本原理和基本用法,我们并没有讲多线程的断点续传,那么这一节我们就接着上一节来讲断点续传,断点续传的重要性不言而喻,可以不用重复下载,也可以节省时间,实 ...

  9. 基于mysqldump备份集来恢复某个误操作的表(drop,truncate)

      Preface       How to rescue a dropped or truncated table online?Dropping or truncating is ddl oper ...

  10. 哲学家就餐-同步问题解析-python

    五个哲学家吃五盘通心粉,由于通心粉很滑,所以必须要拿起左右两边的叉子才能吃到. 叉子的摆放如图所示. 那么问题来了:能为每一个哲学家写一段描述其行为的程序,保证不会出现死锁. 解法1:让他等待能够使用 ...