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

【模板】同余方程

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;
        }
    }
}

全部评论

相关推荐

安静的鲸鱼offer...:神仙级别hr,可遇不可求,甚至他可能也是突然有感而发。只能说遇上是件幸事。
秋招开始捡漏了吗
点赞 评论 收藏
分享
10-15 10:23
门头沟学院 Java
牛可乐的头像真牛:赶紧举报,这公司绝对是诈骗的,等你签约后工作一两个月后根据合同漏洞把你开除,并且要求你赔偿3w培训费,996是为了提前筛选心甘情愿签下合同容易受骗的群体,纯粹面向校招生精心设计的骗局
你见过哪些工贼行为
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务