逆元求法,中国剩余定理加拓展

B站逆元视频的讲解

//x为a%b的逆元,y为b%a的逆元,结果可能会小于零,若小于零,手动x+=b,y+=a
//只有当a,b互质时(即gcd的返回值为1)x,y才有效
int ex_gcd(int a, int b, int &x, int &y)
{
    if (b == 0)//b==0时得到gcd的结果,即a'=gcd(a,b)这里的a'和a是两个值,所以x=1
    {
        //一组特解,y可以取任意数,但是y=0时得到的逆元是最小的
        x = 1;
        y = 0;
        return a;
    }
    int ans = ex_gcd(b, a % b, x, y);
    //由最下面一层递归往回计算x,y的值
    int t = x;
    x = y;
    y = t - (a / b) * y;
    return ans;//返回最小公约数
}

用这个算法来求解中国剩余定理
参考了一位博主的办法:博主文章链接

第一步:
先找出三个数,分别是a和b的公倍数中能被c除余1的最小数,a和c的公倍数中能被b除余1的最小数,b和c的公倍数中能被a除余1的最小数。
以a和b的公倍数中能被c除余1的最小数为例:只要将a,b的最小公倍数乘上对c(mod)的逆元即可:

ex_gcd(a*b,c,x,y);
int num1=a*b/gcd(a,b)*x;

对于剩下两个数也做一样的处理。得到num2,num3。

ex_gcd(a*c,b,x,y);
int num2=a*c/gcd(a,c)*x;
ex_gcd(b*c,a,x,y);
int num3=b*c/gcd(b,c)*x;

然后第二步:

num1=num1*o;
num2=num2*n;
num3=num3*m;

第三步:
将三个数加起来除以a,b,c的最小公倍数取余就可得到x的最小值

int gbs=a*b*c/gcd(gcd(a,b),c);
int ans=(num1+num2+num3)%gbs;

以一个例子来验证一下:

#include <bits/stdc++.h>
using namespace std;
int ex_gcd(int a, int b, int &x, int &y)
{
    if (b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    int ans = ex_gcd(b, a % b, x, y);
    int t = x;
    x = y;
    y = t - (a / b) * y;
    return ans;
}
int gcd(int a, int b)
{
    if (b == 0)
        return a;
    return gcd(b, a % b);
}

int china_rest(int a, int b, int c, int m, int n, int o)
{
    int x, y;
    //第一步
    ex_gcd(a * b, c, x, y);
    int num1 = a * b / gcd(a, b) * x;
    ex_gcd(a * c, b, x, y);
    int num2 = a * c / gcd(a, c) * x;
    ex_gcd(b * c, a, x, y);
    int num3 = b * c / gcd(b, c) * x;
    //第二步
    num1*=o;
    num2*=n;
    num3*=m;
    //第三步
    int gbs=a*b*c/gcd(gcd(a,b),c);
    return (num1+num2+num3)%gbs;
}

int main()
{
    int m,n,o,a,b,c;
    cin>>a>>b>>c>>m>>n>>o;
    cout<<china_rest(a,b,c,m,n,o)<<endl;
    return 0;
}

以下为输入和输出结果
输入和输出结果
那么,如果将式子改到四个或更多呢?以四个为例

实际上我们可以先算前面三个,当成普通的中国剩余问题来算,那么最终结果一定是前面三个式子结果的倍数。

那么问题就转换成了一个式子的问题,从而又一次回到了逆元的计算。

假设t对d(mod)的逆元为q,那么

k*t=t*q*p/(a*b*c*d)/gcd(gcd(a,b),gcd(c,d));

对于更多的式子,只要重复这样的过程,不断往后算即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值