program p1061;
var x,y,n,m,l,a,b,d,xx,yy:int64;
function exgcd(a,b:int64;var x,y:int64):int64;
var t:int64;
begin
if b=0 then
begin
x:=1;y:=0;
exgcd:=a;
end
else
begin
exgcd:=exgcd(b,a mod b,x,y);
t:=x;x:=y;y:=t-a div b*y;
end;
end;
begin
read(x,y,m,n,l);
a:=(m-n+l) mod l;
b:=(y-x+l) mod l;
d:=exgcd(a,l,xx,yy);
if b mod d<>0 then
writeln('Impossible')
else
begin
xx:=(xx*b div d) mod l;l:=l div d;
if xx<0 then xx:=(xx+l*((-xx) div l+1)) mod l;//!!
if xx-l>0 then xx:=xx mod l;//!!
write(xx);
end;
end.
根据题目可得方程(m-n)xx=(y-x) mod l
令a=m-n,b=y-x要把a,b转换成正整数,在模l下加l即可
a*xx+l*yy=b
如果gcd(a,l)|b,那么方程有解(特别考虑,如果m-n=a=0,gcd(a,l)=l,可以直接判断出来不整除,或者同起点,可以整除)
扩展欧几里德求的是它:a*xx+l*yy=gcd(a,l)的解xx
原方程的解为xx:=xx*(b div gcd(a,l))
这里的转化只是一个可行解,并不一定是最小且是正整数
如果xx<0,不断+l div gcd(a,l)直到变成正的
如果xx>l div gcd(a,l),xx:=xx mod (l div gcd(a,l));
为什么是l div gcd(a,l):把xx=xx*(b div gcd(a,l)),yy=yy*(b div gcd(a,l))带入原方程,两边同时约去b,变成a div gcd(a,l)*xx+l div gcd(a,l)*yy=1,变成了模l div gcd(a,l)下的方程
注意要用if判断是否是上面两种情况,用公式算出结果,否则会超时
不要用while!