zoukankan      html  css  js  c++  java
  • Euclid算法

    看了几天挑战编程的数论,颇有感触,尤其是欧几里得算法,特此记下笔记(毕竟书是借的)。   

    整除:对于整数a和b, 若存在整数k使得a = bk, 则称b整除(divides)a(用b|a来表示)。b|a也可以说成b是a的约数,或者a是b的倍数(multiple)。

    唯一分解定理:x能唯一的表示成它的素因数的乘积。

    如果两个整数的最大公约数(greatest common divisor)(也称gcd)是1,称二者是互素(relatively prime)的。

    Euclid算法gcd(a,b)=gcd(b,a%b)

    Euclid算法的证明

    1.如果b|a,则gcd(a,b)= b。因为如果b整除a,则存在整数k,使得a=bk,因此gcd(bk,b)=b。

    2.如果存在整数t和r,使得a=bt+r,则gcd(a,b)=gcd(b,r)。因为gcd(a,b)=gcd(bt+r,b),由于bt是b所有约数的倍数,所以a和b的所有公约数都应该能整除r。

    Euclid算法还能找出两个x和y,使得

       a*x+b*y=gcd(a,b)

    求法:

    我们知道gcd(a,b)=gcd(b,a'),其中a‘=a-b*floor(a/b)。根据数学归纳原理,假设我们已经找出整数x’和y‘,使得

       b*x'+a'*y'=gcd(a,b)

    把a'的表达式带入上式,得到:

       b*x'+(a-b*floor(a/b))*y'=gcd(a,b)

    联立得:

       a*x+b*y=b*x'+(a-b*floor(a/b))*y'

    将等号右边整理下:

       a*x+b*y=a*y'+b*(x'-floor(a/b)*y')

    得到

       x = y', y = x'-floor(a/b)*y'

    由此我们得到了x和y的表达式。

    算法边界的情况:

       a*1+0*0=gcd(a,0)

    代码如下:

    /* Find the gcd(p, q) and x,y such that p*x + q*y = gcd(p, q) */
    //例如对于两个数34398和2132, 有34398*15+2132*(-242)=26
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    long gcd(long p, long q, long *x, long *y){
        long nx, ny, g;
    
        if(q > p) return (gcd(q, p, y, x));
    
        if(q == 0){
            *x = 1;
            *y = 0;
            return (p);
        }
    
        g = gcd(q, p%q, &nx, &ny);
    
        *x = ny;
        *y = (nx - (p/q)*ny);
    
        return g;
    }
    
    int main(){
        long p, q, x, y, g;
        p = 34398; q = 2132;
        g = gcd(p, q, &x, &y);
    
        printf("%ld*%ld+%ld*%ld=%ld\n", p, x, q, y, g);
    
        return 0;
    }

     《算法竞赛入门经典——训练指南》上的代码(和上面一样,只是更简洁):

    void gcd(LL a, LL b, LL &d, LL &x, LL &y) {
        if(!b) { d = a; x = 1; y = 0; }
        else { gcd(b, a%b, d, y, x); y -= x*(a/b); }
    }

    d 代表 a 和 b 的最大公约数, 找出 x、y, 使得 ax+by=d。在此前提下 |x|+|y| 取最小值。

    //2013-04-02 20:20:12

    //2013-05-27 19:50:24 增加《训练指南》上的代码。

  • 相关阅读:
    ASP.NET Core 中间件 中间件(Middleware)和过滤器(Filter)的区别
    ASP.NET Core 中间件详解及项目实战
    开源项目1:某大学校友管理系统
    web安全浅析
    p2p网贷平台设计简析
    一些常见的并且比较难解决的设计问题
    CentOS 新增swap交换空间
    策略模式
    Centos6.4 本地yum源配置
    Linux(CentOs6.4)安装Git
  • 原文地址:https://www.cnblogs.com/tanhehe/p/2996375.html
Copyright © 2011-2022 走看看