poj 1061 青蛙的约会

来源:互联网 发布:长篇小说投稿 知乎 编辑:程序博客网 时间:2024/05/21 09:31

先让我吐槽一番
啊啊啊啊啊恶心的数论让我颓了一下午的数论!
数论最恶心,数论最恶心,数论最恶心……重要的事情说三遍!
不管了好不容易懂了一个数论题,赶紧跑来写博客(以后不会了就来):

————————萌萌哒分割线———————–

poj 1061 青蛙的约会

前言
先来一段exgcd推导:
–>对于方程 ax+by=c;
–>当且仅当 c=k*gcd(a,b)时,方程有解;
–>我们把a,b分别换成b,a%b,等式依然成立(显然);
–>设d=gcd(a,b);
–>等式变成:b*x+(a%b)*y=d;
–>即:bx+(a+⌊a/b⌋*b)*y=d;
–>即:ay+(x-⌊a/b⌋y)*b=d;
–>又d=gcd(a,b)=ax+by(回到最初方程);
–>根据恒等 有:x=y,y=x-⌊a/b⌋y
–>于是就有在递归求解gcd时,顺便解了x,y
代码:

int exgcd(int a,int b,int &x,int &y){    if(!b)    {        x=1;        y=0;        return a;    }    int q=exgcd(b,a%b,x,y);    int t=x;    x=y;    y=t-a/b*x;    return q;}

注意一点:我们递归的边界,x=1,y=0;
//重要的一点//如果(x,y)是一组解,那么(x-b/d,y+a/d)也是一组解

那么回到主题
–><青蛙的约会><–
两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。
我们把这两只青蛙分别叫做青蛙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,y,一个一次跳m个单位,另一只n个,然后跳啊跳啊跳,每次跳到长度L时 就从0开始,他俩同时跳,问最少跳多少次,他们能相遇(同时)

列出方程———>x+am≡y+an(%L)
即:a(m−n)≡y−x(%L)
即:a(m−n)+k*L=y−x
下一步:
用exgcd求解方程a(m−n)+k*L=gcd(m−n,L)
我们换一下:
设:
a=m-n;
c=y-x;
未知数变成了x,y
则:ax+by=c;
那么我们就回到了之前的解方程

—————————等等….!——————————-

但是!!!!这题。。。真的有这么简单么?!

当然没有

如果我告诉你m-n可能小于0?
–>这个简单 特判一下就行了

如果我告诉你最后答案是(a∗c/d)%(L/d)?

我们推导一下这个答案:
设要解的方程(求x)是:
ax’+by’=c
我们现在解了:
ax+by=d
将第二个方程左右同时乘c/d:
ax∗c/d+by∗c/d=c
所以:
x’=x∗c/d
然鹅这样并没有完,因为这只是一组解,我们要求最小正整数解。
我之前已经扯到过:
如果一组 (x,y) 是ax+by=c的一组解,那么(x−b/d,y+a/d)也是原方程的一组解。
这样我们只需要让解得的x不断减b/d,直到再减x下去就会变成负数时,所得的x就是我们要的解。
其实这个过程就是模运算,所以最小正整数解就是:
x’=(x∗c/d)%b/d

ok
扯了这么多 终于可以上代码了:

!!注意!! 要开long long

#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<cmath>#include<algorithm>typedef long long ll;using namespace std;ll xi,yi,m,n,b,a,c,d,x,y; ll exgcd(ll a,ll b,ll &x,ll &y){    if(!b)    {        x=1;        y=0;        return a;    }    ll q=exgcd(b,a%b,x,y);    ll t=x;    x=y;    y=t-a/b*x;    return q;}int main(){    cin>>xi>>yi>>m>>n>>b;    a=m-n;    c=yi-xi;    if(m==n) cout<<"Impossible";    else    {        if(a<0)        {            a=-a;            c=-c;        }        d=exgcd(a,b,x,y);        if(c%d) cout<<"Impossible";        else         {            ll ans;            ans=((x*c/d)%(b/d)+(b/d))%(b/d);            cout<<ans;        }      }                             return 0;}