• 青蛙的约会 扩展欧几里得 方程ax+by=c的整数解 一个跑道长为周长为L米,两只青蛙初始位置为x,y;(x!=y,同时逆时针运动,每一次运动分别为m,n米;问第几次运动后相遇,即在同一位置。


    
    
    /**
    题目:青蛙的约会
    链接:https://vjudge.net/contest/154246#problem/R
    题意:一个跑道长为周长为L米,两只青蛙初始位置为x,y;(x!=y,同时逆时针运动,每一次运动分别为m,n米;问第几次运动后相遇,即在同一位置。
    如果永远无法相遇输出Impossible。
    思路:
    设:次数为t;
    圈总长为: L
    A位置:(x+m*t)%L;
    B位置: (y+n*t)%L;
    
    如果:  (x+m*t)%L = (y+n*t)%L 存在碰面; 暴力枚举t。太大了;
    
    保证m,n<L; m%=L; n%=L; 又x!=y;
    
    => (x+m*t - (y+n*t)) %L = 0;
    设:x+m*t-y-n*t = L*k; (k为整数);
    
    =>(x-y)+(m-n)*t = L*k;
    
    L*k-(m-n)*t = (x-y); 未知数(k, t);
    
    换位置:(m-n)*t - L*k = (y-x)
    
    令:ax+by = c;
    
    a = m-n;
    b = -L;
    c = y-x;
    
    然后根据:
    方程ax+by=c的整数解(a,b,c为整数)
    令g=gcd(a,b), 很明显,c不是g的倍数时方程无解。如果c等于g,用扩展欧几里德算法求得一组解(x0,y0). 如果c是g的倍数,则相应的一组解(x0*c/g,y0*c/g).
    若方程存在解(x1,y1),则通解形式为(x1+k*b/g, y1-k*a/g), k为任意整数
    
    
    */
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int inf = 0x3f3f3f3f;
    const int maxn = 1e5+10;
    const double eps = 1e-6;
    ll gcd(ll a,ll b)
    {
        return b==0?a:gcd(b,a%b);
    }
    ll ext_gcd(ll a,ll b,ll &x,ll &y)
    {
        ll ret, tmp;
        if(!b){
            x = 1, y = 0; return a;
        }
        ret = ext_gcd(b,a%b,x,y);
        tmp = x;
        x = y;
        y = tmp-a/b*y;
        return ret;
    }
    int main()
    {
        ll x, y, m, n, L;
        while(scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&L)!=EOF)
        {
            ll a, b, c;
            a = m-n;
            b = -L;
            c = y-x;
            if(c%gcd(a,b)!=0){
               printf("Impossible
    "); continue;
            }
            ll xx, yy;
            ll d = ext_gcd(a,b,xx,yy);
            ll add = b/d;
            ll t = xx*c/d;
            if(add<0) add = -add;
            t %= add;
            if(t<=0) t+=add;
            printf("%lld
    ",t);
        }
        return 0;
    }
    
    
    
    
    下面这一份是自己最开始写的方法。很繁琐。
    
    
    

    /*
    * 题目:青蛙的约会 链接:https://vjudge.net/contest/154246#problem/R 题意:一个跑道长为周长为L米,两只青蛙初始位置为x,y;(x!=y,同时逆时针运动,每一次运动分别为m,n米;问第几次运动后相遇,即在同一位置。 如果永远无法相遇输出Impossible。 思路: 设:次数为t; 圈总长为: L A位置:(x+m*t)%L; B位置: (y+n*t)%L; 如果: (x+m*t)%L = (y+n*t)%L 存在碰面; 暴力枚举t。太大了; 保证m,n<L; m%=L; n%=L; 又x!=y; => (x+m*t - (y+n*t)) %L = 0; 设:x+m*t-y-n*t = L*k; (k为整数); =>(x-y)+(m-n)*t = L*k; L*k-(m-n)*t = (x-y); 未知数(k, t); 令:ax+by = c; a = L; b = -(m-n); c = (x-y); 为了保证c为正数,所以要处理一下符号关系。暂且当做已经处理过。 把负号都放入未知数中。那么要判断是否这样处理过,如果处理过,那么得出来的K,t要取反。 题目应该是求最小的满足的解t>=1; 然后根据: 方程ax+by=c的整数解(a,b,c为整数) 令g=gcd(a,b), 很明显,c不是g的倍数时方程无解。如果c等于g,用扩展欧几里德算法求得一组解(x0,y0). 如果c是g的倍数,则相应的一组解(x0*c/g,y0*c/g). 若方程存在解(x1,y1),则通解形式为(x1+k*b/g, y1-k*a/g), k为任意整数 */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <set> #include <vector> #include <cmath> using namespace std; typedef long long ll; typedef unsigned long long ull; const int inf = 0x3f3f3f3f; const int maxn = 1e5+10; const double eps = 1e-6; ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); } ll ext_gcd(ll a,ll b,ll &x,ll &y) { ll ret, tmp; if(!b){ x = 1, y = 0; return a; } ret = ext_gcd(b,a%b,x,y); tmp = x; x = y; y = tmp-a/b*y; return ret; } int main() { ll x, y, m, n, L; while(scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&L)!=EOF) { int flag = 0;///flag==0表示正数,否则表示负数; ll a, b, c; a = L; b = m>n?(m-n):(n-m); c = x>y?(x-y):(y-x); if(m-n==0){ printf("Impossible "); continue; } if(x>y){ if(m>n) flag = 1; }else { if(m<n) flag = 1; } if(c%gcd(a,b)!=0){ printf("Impossible "); continue; } ll xx, yy; ll d = ext_gcd(a,b,xx,yy); ll ans = inf; ll add = -a/d;//<0 ll t = yy*c/d; if(flag){///t应该为负数,取反才为正数。 if(t>=0){ t %= (-add); while(t>=0){ t += add; } ans = -t; }else { t = (-t)%(-add); t = -t; if(t==0){ ans = -add; } while(t<0){ ans = -t; t -= add; } } }else {///t应该为正数。 if(t>0){ t %= (-add); while(t>0){ ans = t; t += add; } }else { t = (-t)%(-add); t = -t; while(t<=0){ t -= add; } ans = t; } } if(ans==inf){ printf("Impossible "); continue; }else printf("%lld ",ans); } return 0; }
  • 相关阅读:
    数据库结构中的"树"
    Jquery学习
    cms系统也不复杂
    让你的博客园变灰
    IList对象排序方法
    计算机简介(二)
    在同一台电脑上使用U盘时快时慢的解决方法
    计算机简介
    合并排序
    javascript小结
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/6710669.html
Copyright © 2020-2023  润新知