把矩形展开,我们观察发现,小球总是在m*n/(gcd(m,n))时间停止,所以把矩形展开到边长为m*n/(gcd(m,n))的正方形。然后把要求的点扩展,对于点(x,y),他扩展的点横坐标为2*k+x或2*k-x,纵坐标为2*s+y或2*s-y。k,s 为常数,这样我们的问题转换为求
2*k*n ±x=2*s *m±y. 这个等式的最小解,即求最小的k,s满足等式。最后的答案就是2*k*n ±x。
通过扩展欧几里得,在加上改进,可以求ax+by=c中最小的x,y (a,b,c为常数)满足等式。那么问题就可以解决
#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
#include<cstdio>
#include<math.h>
#include<vector>
using namespace std;
long long c;
long long maxn;
long long n,m,k;
long long dx,dy;
int gcd(long long a,long long b)
{
return b ? gcd(b,a%b) : a;
}
long long extended_euclid(long long a,long long b,long long &x,long long &y)
{
if(b==0) //即gcd(a,b)=a
{
x=1;y=0;
return a;
}
long long n=extended_euclid(b,a%b,y,x); //最大公约数相等
y-=a/b*x;
return n;
}
//ax+by=c
long long kk(long long a, long long b, long long c, long long &x, long long &y)
{
long long g = extended_euclid(a, b, x, y);
if(c % g) return -1;
long long ran = b / g;
x *= c/g;
if(ran < 0) ran = -ran;
x = (x%ran + ran) % ran;
return 0;
}
long long check(long long x,long long y,long long dx,long long dy)
{
if(kk(2*n,-2*m,y-x,dx,dy)==-1)
{
return maxn+1;
}
else
{
if(2*n*dx+x>maxn||2*n*dx+x<0)
return maxn+1;
//cout<<y-x<<" "<<dx<<" "<<dy<<endl;
return 2*n*dx+x;
}
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&k);
maxn=n*m/(gcd(n,m));
long long x,y;
for(int i=0;i<k;i++)
{
scanf("%lld%lld",&x,&y);
//cout<<c<<endl;
//cout<<dx<<" "<<dy<<endl;
long long ans=maxn+1;
ans=min(ans,check(x,y,dx,dy));
//cout<<ans<<"c"<<endl;
ans=min(ans,check(-x,y,dx,dy));
//cout<<ans<<"c"<<endl;
ans=min(ans,check(x,-y,dx,dy));
//cout<<ans<<"c"<<endl;
ans=min(ans,check(-x,-y,dx,dy));
//cout<<ans<<"c"<<endl;
if(ans==maxn+1)
printf("-1\n");
else
printf("%lld\n",ans);
}
//system("pause");
}