青蛙的约会(扩展欧几里得模板题(模板已升级))

来源:互联网 发布:linux系统命令 编辑:程序博客网 时间:2024/05/21 17:04


Link:http://poj.org/problem?id=1061


青蛙的约会
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 98118 Accepted: 18589

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

Source

浙江


编程思想:依题意,可推出公式为 (x + m * s) - (y + n * s) = k * L(k = 0, 1, 2,...),公式化简,得 (n-m) * s + k * l = x - y。令a= (n-m),x=s,b= l ,y=k,c=x - y,即转化为模板题,判断a * x + b * y = c,是否存在整数解。可用扩张欧几里得求解该线性方程。

下面代码中的扩张欧几里得模板来自:http://blog.csdn.net/zhengnanlee/article/details/11607755


AC code:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <set>#include <map>#include <queue>#define PI acos(-1.0)#define LINF 1000000000000000000LL#define eps 1e-8#define LL long long#define MAXN 100010 using namespace std;const int INF=0x3f3f3f3f;LL gcd(LL a, LL b){    return b ? gcd(b, a%b) : a;}//find x, y that satisfied the equation ax+by=d, which minimize the {|x|+|y|}. ps:d = gcd(a,b).void exgcd(LL a, LL b, LL &d, LL &x, LL &y){    if (!b)    {        d = a, x = 1, y = 0;    }    else    {        exgcd(b, a %b, d, y, x);        y -= x * (a / b);    }}//1、先计算Gcd(a, b),若n不能被Gcd(a, b)整除,则方程无整数解;否则,在方程两边同时除以Gcd(a, b),得到新的不定方程a' * x + b' * y = n',此时Gcd(a', b')=1;//2、利用上面所说的欧几里德算法求出方程a' * x + b' * y = 1的一组整数解x0, y0,则n' * x0,n' * y0是方程a' * x + b' * y = n'的一组整数解;//3、根据数论中的相关定理,可得方程a' * x + b' * y = n'的所有整数解为://x = n' * x0 + b' * t//y = n' * y0 - a' * t//(t为整数)bool getans(LL a, LL b, LL c, LL &ans)// ax + by = c 最小整数解{    LL r = gcd(a, b), y0;    if (c%r)//no solutions    {        return false;    }    a /= r, b /= r, c /= r;    exgcd(a, b, r, ans, y0);//至此,上面的说明解决了    LL t = c * ans / b;    ans = c * ans - t * b;    /*此时方程的所有解为:x = c*ans - b*t, x的最小的可能值是0    令x = 0可求出当x最小时的t的取值,但由于x = 0是可能的最小取值,实际上可能x根本取不到0    那么由计算机的取整除法可知:由 t = c*k1 / b算出的t    代回x = c*ans - b*t中,求出的x可能会小于0,此时令t = t + 1,求出的x必大于0;    如果代回后x仍是大于等于0的,那么不需要再做修正。*/    if (ans < 0)    {        ans += b;    }    return true;}LL x,y,m,n,L,a,b,c,ans;bool fg;int main(){while(scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&L)!=EOF){a=n-m;b=L;c=x-y;fg=getans(a,b,c,ans);if(!fg){printf("Impossible\n");}else{printf("%lld\n",ans);}}    return 0;}


扩张欧几里得模板升级版:

AC code:

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <vector>#include <string>#include <queue>#include <stack>#include <algorithm>#define PI acos(-1.0)#define LINF 1000000000000000000LL#define eps 1e-8#define LL long long#define MAXN 100010 #define MOD 1000000007using namespace std;const int INF=0x3f3f3f3f;LL exgcd(LL A,LL &x,LL B,LL &y){    LL x1,y1,x0,y0;    x0=1;y0=0;    x1=0;y1=1;    LL r=(A%B+B)%B;    LL q=(A-r)/B;    x=0;y=1;    while(r)    {        x=x0-q*x1;        y=y0-q*y1;        x0=x1;        y0=y1;        x1=x;y1=y;        A=B;B=r;r=A%B;        q=(A-r)/B;    }    return B;}LL x,y,m,n,L,a,b,c,ans;  int main(){    while(scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&L)!=EOF)      {    a=n-m;    b=L;         c=x-y;         LL x0,y0,flag=0,x,y,min_x,min_y;        if(a<b){flag=a;a=b;b=flag;flag=1;}//默认令a>=b,flag=1说明有交换,则对应的系数x和y最后输出时也要交换后输出         int d=exgcd(a,x0,b,y0);//返回a、b的最大公约数         //求ax+by=c         if(c%d!=0)//无解         {        printf("Impossible\n");}else{x0=x0*(c/d);//x的一个解        y0=y0*(c/d);//y的一个解        LL t=y0/(a/d),minx=INF,miny=INF;        for(int i=t-1;i<=t+1;i++)        {        //x的所有解是x=x0+b/d*t,y的所有解是:y=y-a/d*t。            x=x0+b/d*i;            y=y0-a/d*i;            /*if(fabs(x)+fabs(y)<min)            {                min=fabs(x)+fabs(y);                min_x=fabs(x);                min_y=fabs(y);            }*/            //printf("%d %d\n",x,y);              if(x>=0)            {            minx=min(minx,x);}            if(y>=0)            {            miny=min(miny,y);}        }        /*if(flag)printf("%lld %lld\n",min_y,min_x);        else printf("%lld %lld\n",min_x,min_y);*/        if(flag)printf("%lld\n",miny);        else printf("%lld\n",minx);        //printf("%lld\n",minx);  }    }    return 0;}


0 0
原创粉丝点击