zoukankan      html  css  js  c++  java
  • 拓展欧几里得算法

    学习拓展欧几里得算法的目的是为了解决直线上的点的问题:求直线ax + by +c = 0 上有多少个整点(x, y)满足x∈[x1, x2], y∈[y1, y2];(在此为了推导方便,把ax +by + c = 0换成 ax +by = c, 效果相同)

    在下面我会用@1解决@2,再用@2解决@3,最后回来解决@1, 这样就解决了@3(直线上的点的问题)

    拓展欧几里得算法: ax + by = gcd ( gcd 表示gcd(a, b), 下同)         @1

    假设c/gcd为整数, 上式两边*(c/gcd)      得ax(c/gcd) + by(c/gcd) = c           @2   (若c/gcd不为整数解,则直线上的点的问题也不会有整数解)

    由上式解可得ax + by = c 的一组解 ,即可得直线上的点的问题的一组解。 由这组解(x。, y。)去求全部解:(x。+s。,y。- t。);                 @3

    a(x。+s。) + b(y。- t。) = c ,结合ax。+by。= c可得:as。= bt。两边 / gcd ,得:a / gcd *s。= b / gcd * t。由于a/gcd与b/gcd互质,则s。必为b/gcd的倍数,

    设为s。= k*b/gcd , 可推出t。= k*a/gcd

    则ax + by =c 的解为x = x。+k*b/gcd, y = y。- k *a/ gcd;    k 为任意整数

    x 的最小非负数解为((x。%  (b/gcd) ) + b/gcd)%(b/gcd)   写的这么麻烦是防止x。为负数时出错

    注意(x。, y。)是ax+by = c的一组解,直线上点的坐标要用拓展欧几里得里的解表示则为:x = x 1c/gcd+ kb/gcd; y = y 1c/gcd - ka/gcd (x1, y1)为拓展欧几里得里的一组解

    回来解决@1:

    我们先解决这个问题:    若ax 1+ by1=gcd, bx2 + (a%b)y2 = gcd ,如何通过(x2, y2)求得(x1, y1)的一组解

    首先 :a%b = a- a/b*b    (计算机的思维就是这么妙) 

    联立上式得:ax1+by1=ay2 + b(x2-(a/b)y2) ,可以得到它的一组解(注意就是一组解) x1 = y2;  y1 =x2 - (a/b)y2            @4

    解决这个问题后,我们就来解决ax+by =gcd的问题

    首先gcd(a, b)  = gcd ( b, a%b) ,边界:b = 0

    则把上式不断变换,得到 a * x + 0 * y= gcd(a, 0) = a, 注意:这里的a,x,y都不是原来的a, x, y了, 在这里可取 x =1 , y =0 ; a = gcd (a, 0) = gcd(gcd为原来的a,b 的最大公因数),可得a值 

    然后通过@4的式子不断回溯,可得最初的ax + by = gcd 的一组解

    最后和@3中差不多 ,设全部解:(x1+s。,y1 - t。),然后代入,解得x = x1+k*b/gcd, y = y1- k *a/ gcd; 

    x 的最小非负数解为((x1%  (b/gcd) ) + b/gcd)%(b/gcd)  

    拓展欧几里得算法:

     1 int exGcd(int a, int b, int &x, int &y)
     2 {
     3     if(b == 0)
     4     {
     5         x = 1;
     6         y = 0;
     7         return a;
     8     }
     9     int g = exGcd(b, a % b, x, y);      //g 是 gcd 
    10     int temp = x;
    11     x = y;
    12     y = temp - a / b * y;
    13     return g;
    14 }

    嗯,基本就是这些了

    补充:

    1.思考了a, b为负数的情况,当a,b 为负数时代码应该要有调整,使得传入exGcd的a, b为正数,并对对应的x或y进行取反操作;

  • 相关阅读:
    PS软件之,快速的修改图片你的尺寸
    想的太多,做的太少
    Java-Junit 的Hello world
    Java-hibernate的映射文件
    工作思路
    Spring入门Hello World
    PHP 进制问题
    Java-hibernate的Hello World
    PHP获得header头进行分析
    动软模板使用教程
  • 原文地址:https://www.cnblogs.com/thesky/p/10818111.html
Copyright © 2011-2022 走看看