原题网址:http://codeforces.com/contest/724/problem/C
如同做光学题时把物像翻折,这道题把点不断翻折,可得到一系列的点,就拿横坐标来说,翻折到得点横坐标依次为x,2na-x,2na+x,4na-x,4na+x,纵坐标对应的为y,2ma-y,2ma+y,4ma-y,4ma+y……
现在我们要找的是原来的点和翻折的“像”中横纵坐标相等的点,就得到了一个二元一次不定方程2na±x=2mb±y。按理说是要用拓展欧几里得做的,但这道题有一个优雅做法:将式子对2m取模,变为2na≡±x±y(mod 2m),对于2na=c(mod 2m)可以O(m)预处理出每个c对应取得的最小a。这样对于±x±y的值就可以在表中查到a,从而算出时间。
注意在等号一边取了减号的时候a≥1,所以3、4两种情况等式左边都有一个2n。
const
INF=1<<60;
var
f:array[0..200050] of int64;
n,m,k,a,b:int64;
i:longint;
t,ans:int64;
function min(a,b:int64):int64;
begin if (a<b) then exit(a) else exit(b); end;
function mode(x:int64):int64;
begin exit((x mod (m<<1) + (m<<1)) mod (m<<1));end;
begin
read(n,m,k);
for i:=0 to m<<1 do f[i]:=-1;
for i:=m<<1 downto 0 do
f[(n*2*i) mod (m*2)]:=i;//预处理每个值对应的最小a
for i:=1 to k do
begin
read(a,b);ans:=INF;
t:=f[mode(-a+b)];
if (t<>-1) then ans:=min(ans,t*n*2+a);
t:=f[mode(-a-b)];
if (t<>-1) then ans:=min(ans,t*n*2+a);
t:=f[mode(+a-n<<1+b)];
if (t<>-1) then ans:=min(ans,(t+1)*n*2-a);
t:=f[mode(+a-n<<1-b)];
if (t<>-1) then ans:=min(ans,(t+1)*n*2-a);
if (ans=INF) then ans:=-1;
writeln(ans);
end;
end.