欧几里得算法

190 篇文章 2 订阅
54 篇文章 0 订阅

辗转相减法

用于求两数的最大公约数。
a和b两数不断地用大数减小数,再用差和较小数重复以上操作直至两数相等。
例如48和56的最大公约数:
56 48->8 48->8 40->8 32->8 24->8 16->8 8.
故答案为8.
为了优化计算常常将减法改为取余。

代码

int gcd(int a,int b)
{
    if(a<b) swap(a,b);
    while(a!=b&&a&&b)
    {
        a=a%b;
        swap(a,b);
    }
    return a;
}

此时每进行一次操作问题规模都将缩小一倍,故复杂度为log(n)。

扩展 求解(k1*x+k2 *y=1)

假设k1 > k2
如果解决了这个更小的问题
(k1 - k2) * x_1 + k2 * y _1 = 1
就可以由
k1* x_1+k2*(y_1-x _1) = 1
解出 x_1, y_1即可推出x , y。

代码

#include<bits/stdc++.h>
using namespace std;

int x,y;
int qj(int a,int b)
{
    if(b)
    {
        int k=qj(b,a%b);
        x-=(a/b)*y;
        swap(x,y);
        return k;
    }
    else
    {
        x=1;
        y=0;
        return a;
    }
}

int main()
{
    int a,b;
    cin>>a>>b;
    qj(a,b);
    cout<<x<<" "<<y;
}

应用 求乘法逆元

乘法逆元

假设要算 C(n, m) % MOD
本质就是算m! / ( (m-n)! * n!) % MOD
答案肯定是个整数,但是要取余,中间又有除法运算
我们知道乘法与加法减法运算都是可以先取余再运算的,不影响结果。但是除法比如
12 / 3 % 5 = 4
12 % 5 / 3 = 0.666666

计算方法

令 a / b % mod = c
则 a / b = k*mod + c
a = k * b * mod + b * c
这个时候 如果可以找到一个数 inv(b) 使得 b * inv(b) % mod = 1
那么我们给两边同时乘上inv(b) 就有
a * inv(b) = k * mod + c
所以我们就可以巧妙的将原先的除法转换成了乘法
那么这个问题的关键就在于b * inv(b) % mod = 1有解
这实际上就是扩展欧几里得判断是否有解,b 与 mod必须互质

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值