题解 | #【模板】同余方程#

【模板】同余方程

https://ac.nowcoder.com/acm/contest/21289/A

简单的模板题。利用扩展欧几里得即可求。

首先,你要知道在初等数论里,我们把a和b的最大公约数记错记作(a,b),把b可被a整除记作a|b,把b不可被a整除记作a∤b

扩展欧几里得的证明需要用翡蜀定理

对任意的正整数a b,必然存在x y,使得ax+by=(a,b)

  1. 若b=0,那么(a,b)=a。此时定理显然成立
  2. 若(a,b)!=0,那么将ax+by=(x,y)转换成证bx+(a%b)y=(b,a%b),由欧几里得算法得知该式最终会将b变成0,即变成第一步,得证。

当b=0的时候,我们可以看出x=1,y=0必然是个满足的解,那么我们可以通过反递推得到最终的x,y的值。

那么假设原先x,y值为x1与y1,变化后的x,y值为x2,y2。

即得到

ax1+by1=bx2+(b%a)y2(数学语言表达) => ax1+by1=bx2+(b-b/a*a)y2(计算机语言)

展开后我们就可观查得到一个可行解为 x1=y2,y1=x1-[a/b]*y2;

那么我们就可以写出扩展欧几里得的代码

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

得到的x,y就是方程的一个解 但是我们还要求方程的最小正整数解

这就要用到另外一个知识点了,x=x+b/gcd*k的方程的通用解 那么

只要对x取模就能得到最大答案了 附上代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll exgcd(ll a,ll b,ll& x,ll& y)
{
    if(!b)
    {
        x=1;y=0;
        return a;
    }
    ll d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
int main()
{
    ll T,a,b;
    cin >> T;
    while(T--)
    {
        cin >> a >> b;
        if(__gcd(a,b)!=1)
            cout << -1 << endl;
        else
        {
            ll x,y;
            ll gcd=exgcd(a,b,x,y);
            ll tt=b/gcd;
            cout << (x%tt+tt)%tt << endl;
        }
    }
}

全部评论

相关推荐

不愿透露姓名的神秘牛友
09-30 19:49
起名星人:蛮离谱的,直接要求转投销售
投递汇川技术等公司10个岗位
点赞 评论 收藏
分享
2 收藏 评论
分享
牛客网
牛客企业服务