poj1061欧几里德算法

有三个算法:一是著名很简单的gcd算法

其关键在于证明gcd(a, b) == gcd(b, a mod b)

利用整除性来证明,即gcd(a , b) 整除 gcd(b, a mod b),而gcd(b, a mod b)整除gcd(a ,b)

设d = gcd(a , b),a mod b = a - (a / b ) * b,所以d可以整除a mod b, d可以整除b,所以d可以整除b和a mod b 的各种线性组合。而gcd(b, a mod b)是b 和a mod b 的最小线性组合。所以d可以整除gcd(b, a mod b)。同理也可以证明gcd(b, a mod b) 整除 gcd(a , b)


二是求解线性方程ax + by = gcd(a ,b);

采用的是递归的思路,因为gcd(a ,b ) = gcd (b, a mod b)

所以解出了gcd(b, a mod b) = bx_0 + (a mod b)y_0;的话

那么gcd(a, b) = bx_0 + (a - (a / b) * b) y_0;

所以gcd(a, b) = ay_0 + (x_0 - (a / b ) * y_0);

代码:

/**
 *DESCRIPTION:The implement of gcd(a ,b) and ax + by = gcd(a , b)
 *using the equation gcd(a ,b) = gcd(b, a mod b)
 *gcd(a, 0) = a
 */

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

void extended_gcd(long long a, long long b, long long &gcd_d, long long &x, long long &y) {
    if (b == 0) {
        gcd_d = a;
        x = 1;
        y = 0;
    }
    else {
        extended_gcd(b, a % b, gcd_d, y, x);
        y -= (a / b) * x;
    }
}



三:求解同余模方程

ax == b (mod n)

算法导论上有详细解释

有两个定理:

(一):如果方程有解的话必定有gcd(a, n) | b

(二):如果方程有解的话有n / (gcd(a, n))个解

其中最小正数解为(x0 + n) % (n / d)   (d == gcd(a , n));

其中a, b是否为负数没有影响。

poj1061:

#include <iostream>
#include <stdio.h>
using namespace std;

void extended_eculid(long long a, long long b, long long &gcd_d, long long &x, long long &y) {
    if (b == 0) {
        gcd_d = a;
        x = 1;
        y= 0;
    }
    else {
        extended_eculid(b, a % b, gcd_d, y, x);
        y -= (a / b) * x;
    }
}

int main() {

    long long x, y, m, n, L;
    long long a, b, gcd_d, x_0, y_0, ans;
    while (scanf("%lld%lld%lld%lld%lld", &x, &y, &m, &n, &L) != EOF) {
        a = m - n;
        b = y - x;
        /*        if (a < 0) {
            a = -a;
            b = -b;
            }*/
        extended_eculid(a, L, gcd_d, x_0, y_0);
        if ((b % gcd_d) != 0) {
            cout << "Impossible" << endl;
        }
        else {
            ans = (x_0 * b / gcd_d) % L;
            ans = (ans + L) % (L / gcd_d);
            if (ans == 0) {
                ans += L;
            }
            cout << ans << endl;
        }
    }
    return 0;
}

其中注意ans = 0的时候要输出长度L!~

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值