• 青蛙的约会 POJ1061(拓展欧几里得)&& ZOJ-3609 Modular Inverse


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

    题解:

    要求(a)
    x+amy+an (mod L)
    即: a(mn)yx (mod L)
    即: a(mn)+Lk=yx
    用拓展欧几里得求
         a(mn)+Lk=gcd(mn,L)

    令 d=gcd(m-n,L), c=y-x;
    若c%d!=0 则无解。
    解出a后,最终答案为:(ac/d)mod(L/d)

     证明:设要解的方程(求x)是:

            ax1+by1=c

     而我们已经解得

             ax+by=gcd(a,b)=
     此时将第二个方程左右同时乘c/d,则可得:
             axc/d+byc/d=c

     所以:

            x1=xc/d

     这样并没有完,因为这只是一组解,我们要求最小正整数解。

     我们知道:若一组 < x,y > 是ax+by=c的一组解,那么

             <xb/d,y+a/d>

     也是原方程的一组解。

     这样我们只需要让解得的x不断减b/d,直到再减就为负数时,所得的x就是我们要的解。  
     其实这个过程就是模运算,所以最小正整数解就是:

             x1=(xc/d)mod(b/d)
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 typedef long long ll;
     6 ll x,y,m,n,l;
     7 ll ex_gcd(ll a,ll b,ll &x,ll &y)//可以求出a,b和x,y的任意一组值 
     8 {
     9     if(b==0)
    10     {
    11         x=1;
    12         y=0;
    13         return a;
    14     } 
    15     ll q=ex_gcd(b,a%b,y,x);
    16     y-=a/b*x;
    17     return q;
    18 } 
    19 int main()
    20 {
    21     while(~scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l))
    22     {
    23         if(m==n)
    24         {
    25             printf("Impossible
    ");
    26             continue;
    27         }    
    28         if(m<n)
    29         {
    30             ll t=m;
    31             m=n;
    32             n=t;
    33             ll q=y;
    34             y=x;
    35             x=q;
    36         } 
    37         ll c=y-x;
    38         ll a,k;
    39         ll d=ex_gcd(m-n,l,a,k);
    40         if(c%d)
    41             printf("Impossible
    ");
    42         else
    43             printf("%lld
    ",((a*c/d)%(l/d)+(l/d))%(l/d)); 
    44     }
    45 }

     ZOJ-3609  Modular Inverse

    The modular modular multiplicative inverse of an integer a modulo m is an integer xsuch that a-1x (mod m). This is equivalent to ax≡1 (mod m).

    Input

    There are multiple test cases. The first line of input is an integer T ≈ 2000 indicating the number of test cases.

    Each test case contains two integers 0 < a ≤ 1000 and 0 < m ≤ 1000.

    Output

    For each test case, output the smallest positive x. If such x doesn't exist, output "Not Exist".

    Sample Input

    3
    3 11
    4 12
    5 13
    

    Sample Output

    4
    Not Exist
    8
    题意:已知a,m求最小的x满足ax≡1(mod m)
    题解:这个题与上面的思路一模一样,给出两种写法。
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 typedef long long ll;
     8 int casen;
     9 ll ex_gcd(ll a,ll b,ll &x,ll &y)
    10 {
    11     if(b==0)
    12     {
    13         x=1;
    14         y=0;
    15         return a;
    16     } 
    17     ll q=ex_gcd(b,a%b,y,x);
    18     y-=a/b*x;
    19     return q;
    20 } 
    21 int main()
    22 {
    23     ll a,m,x,y,c;
    24     scanf("%d",&casen);
    25     while(casen--)
    26     {
    27         scanf("%lld%lld",&a,&m);
    28         ll d=ex_gcd(a,m,x,y);
    29         if(1%d!=0)
    30         printf("Not Exist
    ");
    31         else
    32         {
    33             ll ans=((x*1/d)%(m/d)+m/d)%(m/d);
    34             if(ans<=0) ans+=m/d;//一定要加上!! 
    35             printf("%lld
    ",ans);
    36         }
    37     }
    38 return 0;
    39 }
    
    

    调用求最小正整数解的函数

    
    
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 typedef long long ll;
     5 using namespace std;
     6 int gcd(int a,int b,int &x,int &y)
     7 {
     8     if(b==0)
     9     {
    10         x=1;
    11         y=0;
    12         return a;
    13     }
    14     int q=gcd(b,a%b,y,x);
    15     y-=a/b*x;
    16     return q;
    17 }
    18 int cal(int a,int b,int c)
    19 {
    20     int x;int y;
    21     int  g=gcd(a,b,x,y);
    22     if(c%g!=0) return -1;
    23     x*=c/g;
    24     b/=g;
    25     if(b<0) b=-b;
    26     ll ans=x%b;
    27     if(ans<=0)
    28     ans+=b;
    29     return ans;
    30 }
    31 int main()
    32 {
    33     int b,x,y,t,n,a,m;
    34     scanf("%d",&t);
    35     while(t--)
    36     {
    37         scanf("%d%d",&a,&m);
    38         b=cal(a,m,1); 
    39         if(b==-1)
    40         printf("Not Exist
    ");
    41         else
    42         printf("%d
    ",b);
    43     }    
    44 return 0;
    45 }
    
    
    
     
  • 相关阅读:
    tcp单线程实现并发
    文件处理
    异常处理、深浅拷贝、基本的文件操作
    列表、元组、字典、集合类型的内置方法
    python进阶之数字类型内置方法和字符串类型内置方法
    九九乘法表和金字塔
    python基础总结
    0801学习整理
    0731学习内容整理
    0730学习内容整理
  • 原文地址:https://www.cnblogs.com/1013star/p/9386688.html
Copyright © 2020-2023  润新知