poj1061

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!

你可能感兴趣的:(poj1061)