• Codeforces Round #305 (Div. 2)——C拓展欧几里得,循环—— Mike and Frog


    Mike has a frog and a flower. His frog is named Xaniar and his flower is named Abol. Initially(at time 0), height of Xaniar is h1 and height of Abol is h2. Each second, Mike waters Abol and Xaniar.

    So, if height of Xaniar is h1 and height of Abol is h2, after one second height of Xaniar will become  and height of Abol will become  where x1, y1, x2 and y2 are some integer numbers and  denotes the remainder of amodulo b.

    Mike is a competitive programmer fan. He wants to know the minimum time it takes until height of Xania is a1 and height of Abol is a2.

    Mike has asked you for your help. Calculate the minimum time or say it will never happen.

    Input

    The first line of input contains integer m (2 ≤ m ≤ 106).

    The second line of input contains integers h1 and a1 (0 ≤ h1, a1 < m).

    The third line of input contains integers x1 and y1 (0 ≤ x1, y1 < m).

    The fourth line of input contains integers h2 and a2 (0 ≤ h2, a2 < m).

    The fifth line of input contains integers x2 and y2 (0 ≤ x2, y2 < m).

    It is guaranteed that h1 ≠ a1 and h2 ≠ a2.

    Output

    Print the minimum number of seconds until Xaniar reaches height a1 and Abol reaches height a2 or print -1 otherwise.

    Sample test(s)
    input
    5
    4 2
    1 1
    0 1
    2 3
    output
    3
    input
    1023
    1 2
    1 0
    1 2
    1 1
    output
    -1
    Note

    In the first sample, heights sequences are following:

    Xaniar: 

    Abol:

    大意:x = (kx+b)%m 在2*m次里面能看出是否能够到达所有的值

    法一:暴力

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    int main()
    {
        long long  m,h1,a1,x1,y1,h2,a2,x2,y2;
        long long  p1,p2,q1,q2;
        while(cin >> m >> h1 >> a1 >> x1 >> y1 >> h2 >> a2 >> x2 >> y2){
            p1 = p2 = q1 = q2 = 0;
            for(long long  i = 1; i <= 2*m; i++){
                h1 = (h1*x1+y1)%m;
                if(h1 == a1){
                    if(p1 == 0)
                        p1 = i;
                    else if(q1 == 0){
                        q1 = i - p1;
                        break;
                    }
                }
            }
            for(long long i = 1; i <= 2*m; i++){
               h2 = (h2*x2+y2)%m;
               if(h2 == a2){
                   if(p2 == 0)
                       p2 = i;
                   else if(q2 == 0){
                       q2 = i - p2;
                       break;
                   }
               }
            }
            if(p1 == 0 || p2 == 0){
                puts("-1");
                continue;
            }
            long long ans1 = p1,ans2 = p2;
            long long i;
            for( i = 1; i <= 2 *m ;i++){
                if(ans1 == ans2){
                    printf("%lld
    ",ans1);
                    break;
                }
                if(ans1 > ans2){
                    ans2 += q2;
                }
                if(ans1 < ans2){
                    ans1 += q1;
                }
            }
            if( i > 2*m){
                puts("-1");
            }
        }
        return 0;
    }
        
    

      

    法二:拓展欧几里得

    用于处理计算ax+by = c 的x,y的值

    由已知数据我们容易可以的出p1,q1,p2,q2,依次是h1到a1的开始的时间,循环的时间,h2到a2的开始的时间,循环的时间,那么可以得到p1x+q1 = p2x+q2

    变形可得 p1x-p2x=q2-q1

    欧几里得 ax+b = c   gcd(a,b) = gcd(b,a%b)  当b=0时就是最大公约数,递归最大公约数的求法

    int gcd(int a,int b){
    return b == 0? a:gcd(b,a%b);

    }

    拓展欧几里得公式 ax+by=c

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

     可以得到其中一个x,y的解(对于ax+by = gcd(a,b) 这个方程)

    定理:对于ax+by = gcd(a,b)来说肯定会存在x,y(为正整数)的解 

    所以最终的解为 x *= c/d,y *=c/d;如果c%d!=0说明无正整数解

    那么对于所有的x,y解集满足条件

    x = x + q2/d;

    y = y - q1/d;

    对于本题来说只要找到一个最小的x满足x,y都大于等于零,res = q1x+p1

    以上都是些结论

    详细证明 请看 http://www.cnblogs.com/ka200812/archive/2011/09/02/2164404.html  大神写的非常好orz

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    long long x,y;
    long long  exgcd(long long  a,long long  b){
        if(b == 0){
            x = 1;
            y = 0;
            return a;
        }
        long long  d = exgcd(b,a%b);
        long long  t = x;
        x = y;
        y = t - a/b*y;
        return d;
    }
    int main()
    {
        long long  m,h1,a1,x1,y1,h2,a2,x2,y2;
        long long  p1,p2,q1,q2;
        while(cin >> m >> h1 >> a1 >> x1 >> y1 >> h2 >> a2 >> x2 >> y2){
            p1 = p2 = q1 = q2 = 0;
            for(long long  i = 1; i <= 2*m; i++){
                h1 = (h1*x1+y1)%m;
                if(h1 == a1){
                    if(p1 == 0)
                        p1 = i;
                    else if(q1 == 0){
                        q1 = i - p1;
                        break;
                    }
                }
            }
            for(long long i = 1; i <= 2*m; i++){
               h2 = (h2*x2+y2)%m;
               if(h2 == a2){
                   if(p2 == 0)
                       p2 = i;
                   else if(q2 == 0){
                       q2 = i - p2;
                       break;
                   }
               }
            }
           long long d = exgcd(q1,-q2);
           long long c = p2 - p1;
           if(d == 0){
               puts("-1");
               continue;
           }
           if(c%d){
               puts("-1");
               continue;
           }
           if(d < 0 ) d = -d;
           if(p1 == 0 || p2 == 0){
               puts("-1");
               continue;
           }
           if(q2 == 0 && q1 == 0 && p1 != p2){
               puts("-1");
               continue;
           }
         //  printf("%I64d %I64d %I64d %I64d
    ",p1,p2,q1,q2);
           if((q2 == 0&&p2-p1 < 0) || (q1 == 0 && p1-p2< 0)){
               puts("-1");
               continue;
           }
         long long   k = c/d;
         if(exgcd(q1,-q2) < 0)
             x = -x,y = -y;
           x*= k; y*= k;
           if(x < 0 || y < 0)
           for( ; ;){
               x += q2/d;
               y += q1/d;
               if(x >= 0 && y >= 0)
                   break;
           }
           if(x > 0 && y > 0){
               for(; ;){
                   x -= q2/d;
                   y -= q1/d;
                   if( x < 0 || y < 0)
                       break;
               }
               x += q2/d;
               y += q1/d;
           }
    
           long long ans = x*q1+p1;
           printf("%I64d
    ",ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    hpuoj--校赛--2015年的第一场雪(暴力)
    hpuoj--校赛--考试来了(水题)
    hpuoj--校赛--特殊的比赛日期(素数判断+模拟)
    bean copy
    spring boot+jaspersoft实现复杂报表
    spring boot 启动时运行代码(2)ApplicationListener
    Alibaba Java Coding Guidelines 安装(eclipse)并简单使用
    spring boot 系统启动时运行代码(1)-@PostConstruct
    java泛型&bean copy list
    jgroups-raft
  • 原文地址:https://www.cnblogs.com/zero-begin/p/4533734.html
Copyright © 2020-2023  润新知