寒假集训专题四-D.同余方程

d-同余方程

解同余方程的通法

注意:gcd的两个参数一定是正值
对于

Ax≡B(mod M)---->Ax=My+B---->Ax+My=B(正负号不重要),因为解出的x或者y可以通过整体式子+-lcm 的倍数来变化
于是就是解Ax+My=B这个不定方程。

根据斐蜀定理:ax+by=c=k∗gcd(a,b)(k∈N∗)
所以必须gcd(A,M)|B,否则无解。

//这里需要特别判断
设a>b。
当b=0,gcd(a,b)=ab=0,gcd(a,b)=a,所以此时x=1,y=0x=1,y=0
当a>b>0a>b>0时,设ax1+by1=gcd(a,b),bx2+(a mod b)y2=gcd(b,a mod b)
根据欧几里德原理,则
ax1+by1=bx2+(a mod b)y2
即ax1+by1=bx2+(a−(a/b)∗b)y2=ay2+bx2−(a/b)∗by2
对应得x1=y2,y1=x2−(a/b)∗y2

于是我们就可以一边求gcd一边解这个方程。
当然,注意到跑了exgcd后解出来的是ax+by=gcd(a,b)
解同时乘上c/gcd(a,b)
注意到x,y的解不止一个x+=b/gcd(a,b),y−=a/gcd(a,b)后总是合法。(因为加减的都是ab/gcd(a,b)=lcm(a,b)
为了求最小正整数值,我们模这个值即可。

求这一步之前,要先判断x的正负与否

如果要把最后一步套路化,就是D=gcd(A,B),x=x∗(B/D)%(M/D)

代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
ll exgcd(ll a, ll b ,ll &x,ll &y)
{
if(b==0) {x=1,y=0;return a;};
ll d=exgcd(b,a%b,x,y);
//这一步交换的处理很重要
ll z=x;x=y,y=z-a/b*y;
return d;
}
ll gcd(ll x,ll y)
{
if(y==0) return x;
return gcd(y,x%y);
}
signed main()
{
ll a,b,x,y;
cin>>a>>b;
ll m=gcd(a,b);
//这里其实要判断 ?gcd(a,b)|1,答案是肯定的,题目已经保证了
ll d=exgcd(a,b,x,y);
if(x<0)
{
while(x<0)
{
x=x+b/m;
}
}
//这里1即同余方程右边的值,由于是1可要可不要
cout<<x*(1/m)%(b/m);
}

本文作者:TimMCBen

本文链接:https://www.cnblogs.com/TimMCBen/p/15996647.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   TimMCBen  阅读(33)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.