辗转相除法,扩展欧几里德算法,线性同余方程(poj 1061)

(poj 1061)http://hi.baidu.com/newmyl/item/dc6805253305833195f62b0a

 http://blog.csdn.net/lansetiankong_yiyi/article/details/5841825

辗转相除法:

递归:

int Gcd(int a, int b)
  {
      if(b == 0)
          return a;
    return Gcd(b, a % b);
  }

非递归:

int Gcd(int a, int b)
  {
      while(b != 0)
      {
          int r = b;
          b = a % b;
          a = r;
      }
      return a;
  }

 

 

 

扩展欧几里德:

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

 

线性同余方程:

求a * x + b * y = n的整数解。

  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

 

求最小:

1。我们往往被要求去求最小整数解,所以我们就可以将一个特解x,t=b/(a,b),x=(x%t+t)%t;就可以了(貌似会产生负数)

2.

t=c*k1/b;//注1

              k1=c*k1-t*b;

              if(k1<0)

                     k1+=b;

注1:(原注1做废)

              此时方程的所有解为:x=c*k1-b*t,x的最小的可能值是0,令x=0可求出当x最小时的t的取值,但由于x=0是可能的最小取值,实际上可能x根本取不到0,那么由计算机的取整除法可知:由 t=c*k1/b算出的t,代回x=c*k1-b*t中,求出的x可能会小于0,此时令t=t+1,求出的x必大于0;如果代回后x仍是大于等于0的,那么不需要再做修正。(地址1,貌似产生的都是正数)

posted on 2013-02-17 21:29  Sure_Yi  阅读(944)  评论(0编辑  收藏  举报

导航