zoukankan      html  css  js  c++  java
  • poj1061 青蛙的约会 && poj 2115 C Looooops<扩展欧几里得>

    链接 :http://poj.org/problem?id=1061 青蛙的约会

       http://poj.org/problem?id=2115  C Looooops

    首先我们先讨论欧几里得算法 ( gcd ):

    gcd( a, b )即求两个数的最大公约数

    递归算法: 

    int gcd( int a, int b )
    {
      return b==0?a:gcd( b, a%b );  //gcd(a,b) = gcd(a%b,b),这个递归一次以后就终止了无法保证a b可以继续减小,所以把 b 和 a%b交换顺序。
    }

    非递归算法:

    int gcd( int a, int b )
    {
      if( b==0 )return 0;
      while(b)
      {
        int t=a%b;
        a=b;
        b=t;
      }
      return a;

    }

    现在我们讨论算法的正确性,即证明gcd(a,b)==gcd(b,a%b),我们只要证明gcd(a,b)==gcd(a-b,b)即可,因为可以由此逐步扩展为gcd(a,b) == gcd(a-k*b,b),而 gcd(a-k*b,b)==gcd(a%b,b)。
    因为a,b的公约数必然是a-b,b的公约数故 gcd(a,b) <= gcd(a-b,b);另a-b b的公约数也必然是a b的公约数,gcd(a,b) >= gcd(a-b,b).所以gcd(a,b) == gcd(a-b,b)。

    再说扩展欧几里得:

    扩展欧几里德算法是用来求解a*x+b*y==gcd(a,b)这样的方程的。同样利用gcd(a,b)==gcd(b,a%b)把a*x+b*y==gcd( a, b )转化为b*x'+(a%b)*y'==gcd( b, a%b );

    根据递归的思想,假设现在我们已经求出了x' y',剩下的关键就是如何用x' y'求出x y.我们观察gcd(b,a%b) = b*x'+(a%b)*y',只要把右边重新写成 a*x+b*y 的形式就行了,所以需要对b*x'+(a%b)*y'进行变形,因为a%b == a-a/b*b,故b*x'+(a%b)y' = b*x'+(a-a/b*b)y' == a*y' + b*(x'-a/b*y') .

    这样便可得出 x = y' y = x'-a/b*y'。

    所以扩展gcd的递归算法为

    LL exgcd( LL a, LL b, LL &x, LL &y )
    {
      LL d, t;
      if( b==0 )
      {
        x=1, y=0;
        return a;
      }
      d=exgcd( b, a%b, x, y );
      t=x, x=y, y=t-a/b*y;
      return d;        // 返回gcd( a, b );
    }

     这样我们就得到了方程的解 :

    x==x0+b*t;    //    特解+通解

    y==y0+a*t; 

    然后再看一般形式 a*x+b*y==c;

    当且仅当 c%gcd( a,b )==0时方程才有解。

    a*x+b*y==c的求解可以先求出a*x+b*y=gcd(a,b),然后将x y扩大c/gcd(a,b)倍就可以了。

     

    View Code
     1 /*
     2 
     3 poj1061
     4 
     5 */
     6 #include <stdio.h>
     7 typedef long long LL;
     8 LL gcd( LL a, LL b )
     9 {
    10     return b==0?a:gcd( b, a%b );
    11 }
    12 void exgcd( LL a, LL b, LL &x, LL &y )
    13 {
    14     if( b==0 )
    15     {
    16         x=1, y=0;
    17         return ;    
    18     }
    19     exgcd( b, a%b, x, y );
    20     LL t=x;
    21     x=y;
    22     y=t-a/b*y;
    23 }
    24 
    25 int main( )
    26 {
    27     LL x, y, m, n, l;
    28     LL a, b, c, k1, k2, r;
    29     while( scanf( "%lld%lld%lld%lld%lld", &x, &y, &m, &n, &l )!= EOF )
    30     {
    31         a=n-m, c=x-y;
    32         r=gcd( a, l );
    33         if( c%r )
    34         {
    35             puts( "Impossible" );
    36             continue;     
    37         }
    38         a/=r, l/=r, c/=r ;
    39         exgcd( a, l, k1, k2 );
    40         LL t=c*k1/l;
    41         k1=c*k1-t*l;
    42         if( k1<0 )
    43             k1 += l;
    44         printf( "%lld\n", k1 );    
    45     }
    46     return 0;
    47 }
    View Code
     1 /*
     2 
     3 poj2115
     4 
     5 */
     6 #include <stdio.h>
     7 typedef long long LL;
     8 LL exgcd( LL a, LL b, LL &x, LL &y )
     9 {
    10     LL d, t;
    11     if( b==0 )
    12     {
    13         x=1, y=0;
    14         return a;    
    15     }
    16     d=exgcd( b, a%b, x, y );
    17     t=x, x=y, y=t-a/b*y;
    18     return d;
    19 }
    20 
    21 // (a+c*m)%2^k=b ==> c*m-n*2^k=b-a;
    22 int main( )  
    23 {  
    24     LL A,B,C,k, a, b, c, x, y, n;  
    25     while(scanf("%lld %lld %Illd %lld",&A,&B,&C,&k))  
    26     {  
    27         if(!A && !B && !C && !k)  
    28             break;  
    29   
    30         a=C, b=B-A, n=(LL)1<<k;  //2^k   
    31         LL d=exgcd(a,n,x,y);  //求a,n的最大公约数d=gcd(a,n)和方程d=ax+by的系数x、y  
    32         if(b%d!=0)  //方程 ax=b(mod n) 无解  
    33            puts("FOREVER"); 
    34         else  
    35         {  
    36             x=(x*(b/d))%n;  //方程ax=b(mod n)的最小解  
    37             x=(x%(n/d)+n/d)%(n/d);  //方程ax=b(mod n)的最整数小解  
    38             printf("%lld\n",x);  
    39         }  
    40     }  
    41     return 0;  
    42 }  

     

  • 相关阅读:
    linux 文件搜索
    解决android 无法打开 DDMS 中的data目录
    JAVA 截图+tess4j识别
    JAVA 获取网页源代码保存到本地文件
    java连接sqlserver数据简单操作
    SQL server 2008 安装提示:属性不匹配
    SQLServer 安装提示需要重启计算机的解决方案
    Android蓝牙----打开,关闭操作
    JAVA中String类的比较
    Android中的AlertDialog和ProgressDialog用法
  • 原文地址:https://www.cnblogs.com/jian1573/p/2603943.html
Copyright © 2011-2022 走看看