zoukankan      html  css  js  c++  java
  • 欧几里德 及 扩展欧几里德

    昨晚看了一点点的数论,是一个直线上的点的例题,正好用到了欧几里德算法。于是就网搜了一下,做一些笔记,以后好留着自己看。

    欧几里德算法其实就是求两个整数的最大公约数的算法,gcd函数应该都知道,gcd(a,b)就是求a,b的最大公约数。根据最大公约数的性质:gcd(a,b) = gcd(b,a) = gcd(b,a%b);

    也就是我们熟悉的辗转相除法,辗转相除的代码

    View Code
    //非递归实现
    int gcd(int a,int b)
    {
    if(a < b) swap(a,b);
    while(b)
    {
    int temp = b;
    b = a % b;
    a = t;
    }
    return a;
    }
    
    //递归实现
    int gcd(int a,int b)
    {
    if(a < b) swap(a,b);
    if(b) gcd(b, a % b);
    return a;
    }


    扩展欧几里德算法

    扩展欧几里德是:对于不全为零的 a , b来说,必然存在整数对 x , y,使得 gcd( a, b) = a * x + b * y 成立。下面是讲如何求解 x , y 。

    设 a>b。

    1. 显然当 b=0,gcd(a,b)=a。此时 x=1,y=0;

    2. ab < > 0 时

    设 a * x1 + b * y1 = gcd(a,b);

    b * x2 + (a mod b) * y2 = gcd(b,a mod b);

    根据欧几里德原理有: gcd(a,b)=gcd(b,a mod b);

    则:a * x1 + b * y1 = b * x2 + (a mod b) * y2;

    即:a * x1 + b * y1 = b * x2 + (a - ( a / b ) * b ) * y2 = ay * 2 + b * x2 - ( a / b ) * b * y2;

    根据恒等定理得:x1 = y2; y1 =x2 - ( a / b) * y2;
    代码实现

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

    欧几里德的一个应用就是求解 线性方程 a * x + b * y + c = 0;的解。

    有上可知方程式  gcd(a , b) = a * x + b * y;可以求出一对整数对 x y 满足该方程,设 d  = gcd( a ,b);

    则对于方程gcd(a , b) = a * x + b * y 变为:d = a * x + b * y  , 方程两边同时除以  d 的 1 = a * ( x / d) + b * ( y / d) ,再同时乘以 c 得 c = a * ( c * x / d ) + b * ( c * y / d) ;所以对于方程 c = a * x + b * y ; 来说,他第一组解即为:

    x1 = c * x / d, y1 = c * y / d (其中 x 和 y是gcd( a,b) = a * x + b * y , 的一组整数解,d 为gcd(a,b)),

    所以对于方程式    c = a * x + b * y   的任意一组解即为 n ,m 则

    n = x1 + b * gcd(a,b) * t; m = y1 - a * gcd(a,b) * t; t 为任意正整数。

    如果 c % gcd(a,b) != 0 则 方程 c = a * x + b * y 无解。

    例题 pku 1061 http://poj.org/problem?id=1061

    根据题意 设 step 青蛙跳的步数

    则有 abs((x + m × t) - (y + n × t)) =  k × L ; 成立

    则有 (m - n) × t - (y - x ) = k × L;

    则有 (m - n ) × t  - k × L = (y - x) 

    所以 令 temp = (m - n),kemp = (y - x),cemp = L;

    则原式变为 temp *  t + cemp * k = kemp;

    即为 a * x + b * y = c;的形式

    参见代码

    View Code
     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<iostream>
     4 using namespace std;
     5 typedef long long ll;
     6 ll temp,kemp;
     7 int exgcd(int a,int b)
     8 {
     9     if(b == 0)
    10     {
    11         temp = 1;
    12         kemp = 0;
    13         return a;
    14     }
    15     ll ans = exgcd(b,a % b);
    16     ll t = temp;
    17     temp = kemp;
    18     kemp = t - a / b * temp;
    19     return ans;
    20 }
    21 int main()
    22 {
    23     ll x,y,m,n,L;
    24     while(cin>>x>>y>>m>>n>>L)
    25     {
    26         if(m == n && x != y)
    27         {
    28             cout<<"Impossible\n";
    29             continue;
    30         }
    31         ll a = m - n;
    32         ll b = L;
    33         ll c = y - x;
    34         if(a < 0)
    35         {
    36             a = -a;
    37             c = -c;
    38         }
    39         ll d = exgcd(a,b);
    40         if(m == n || c % d != 0)
    41         {
    42             cout<<"Impossible\n";
    43         }
    44         else
    45         {
    46             b /= d;
    47             c /= d;
    48             ll t = c * temp;
    49             cout<<(t % b + b) % b<<endl;
    50         }
    51     }
    52     return 0;
    53 }
  • 相关阅读:
    网站、博客、文章推荐
    hdu 4000 Fruit Ninja
    2011年 北京区域赛A题 Qin Shi Huang's National Road System // hdu 4081 Qin Shi Huang's National Road System 最优比率生成树
    2008 北京区域赛 Minimal Ratio Tree
    uva 10608 Friends 并查集
    2011 北京区域赛 Hou Yi's secret // hdu 4082
    C/C++中有关字长与平台无关的整数类型(转)
    C/C++中有关字长与平台无关的整数类型(转)
    C# Windows Media Player 控件使用实例 方法(转)
    c# 系统时间
  • 原文地址:https://www.cnblogs.com/fxh19911107/p/2443832.html
Copyright © 2011-2022 走看看