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!