题435. 同余-acwing-222. 青蛙的约会
一、关于线性同余方程的求解综述
1.对线性同余方程的解释
ax ≡ c (mod b)表示关于x的解集,其中x需满足(a*x)%b=c。求解该问题等价于求解方程ax+by=c(或ax%b==c%b),其中只要x的集合能够被求出,那么y的集合也可以通过x求出。
2.求解线性同余方程的方法:扩展欧几里得算法
(1)关于扩展欧几里得算法:
定义:正如其名,它是欧几里得算法的扩展,在得到整数a,b的最大公约数(我们通过欧几里得算法,即辗转相除法求解a,b最大公约数)后,还希望得到整数x,y,使得ax+by=gcd(a,b)
- 对于整数a>b,当b=0时,gcd(a,b)=a,此时x=1,y=0;(我们知道,欧几里得算法到最后是形参b=0,return a,即a就是等于gcd(a,b),此时又有ax+by=gcd(a,b),那么显然x得等与1,y=0)
- 假设ax+by=gcd(a,b),有x,y的解为x1,y1,则ax1+by1=gcd(a,b),此为①式;
- 由欧几里得算法可知,当b!=0时做的操作为gcd(b,a%b),即进入到的gcd的形参a=b,b=a%b,则可设bx2+(a%b)y2=gcd(b,a%b),此为②式;
- 又由欧几里得算法可知,当b!=0时做的操作为gcd(b,a%b),则gcd(a,b)=gcd(b,a%b),则结合①②式可知ax1+by1=bx2+(a%b)y2;
- 由于a%b=a-(a/b)*b(被除数a等于商a/b乘以除数b加上余数a%b,则余数a%b是等于被除数a减商a/b乘以除数b),则ax1+by1=bx2+(a-(a/b)*b)y2=ay2+bx2-(a/b)*by2,即ax1+by1==ay2+b(x2-(a/b)*y2),此为③式;
- 由恒等定理可知,③式成立则x1=y2,y1=x2-(a/b)*y2 ④;
- 这样我们就得到了x1,y1,即ax+by=c的一组解,x1,y1基于x2,y2;
- 以上操作同样以递归方式实现,是建立在欧几里得递归写法之上,当最后b=0时,递归结束,gcd(a,b)被求出,开始返回。设正处于扩欧函数调用过程中,则x2,y2在递归过程中处于更深的一层递归,x1,y1由那个更深的一层递归调用结束后的赋值语句得到,当最浅的一层递归调用结束时,形参a正等于原线性同余方程中的a,而b亦是如此,则对应的x1,y1即为一组解;
(2)求解线性同余方程
1)方程有整数解的充要条件为gcd(a,b)|c,即c为gcd(a,b)的倍数
2)上述扩欧过程求解了x,y,而对于线性同余方程,我们只需要那个x就好了
3)若x0,y0为方程ax+by=c的一组解,则方程任意解可表示为x=x0+b’t,y=y0-a’t,t∈任意整数,a’=a/gcd(a,b),b’=b/gcd(a,b)
4)特别的,若gcd(a,b)=1,且x0,y0为方程ax+by=c的一组解,则方程任意解可表示为x=x0+bt,y=y0-at,t∈任意整数
5)对于一般的求解线性同余方程问题,往往被要求求出一个最小整数解,该值为x=x0(x0 % t + t)%t,其中t=b/gcd(a,b),对于 4)而言t=b
二、题目
三、题解
那么,对于扩展欧几里得算法求线性方程有解的条件是c%gcd(a,b)==0,即c是gcd(a,b)的倍数,对此即为(b-a)%gcd(m-n,L)==0,否则输出 Impossible。
由于扩展欧几里得求出的是ax+by=gcd(a,b)的x,y的解,因此还需两边同时乘一个倍数c/gcd(a,b)使得右边变成c,x=x*(c/gcd(a,b)),对此即为x=x*[(b-a)/gcd(m-n,L)]。
之后,求x的最小正整数解直接套t=b/gcd(a,b),ans=(x%t+t)%t即可
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ex_gcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=1,y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);//这里直接交换x、y,方便计算
y-=a/b*x;
return d;
}
int main()
{
ll a,b,m,n,L;
cin>>a>>b>>m>>n>>L;
ll x,y;
ll d=ex_gcd(m-n,L,x,y);//a,b,x,y
if((b-a)%d) puts("Impossible");
else
{
x*=((b-a)/d);
ll t=abs(L/d);
cout<<(x%t+t)%t;
}
}