题意:
给定一个矩形,长n宽m, 一束光从矩形的一个顶点发射,角度为45度,遇到墙壁则反射, 只有遇到顶点时被吸收, 给你k个光传感器,光传播的速度是根号二m/s,问经过多少时间,光经过这个传感器, 若不能经过,则输出-1。
思路:
将矩形对称展开,把所有反射当做穿过看待,容易想到光在横纵坐标都为maxnx= m*n/gcd(m,n)(m,n的最小公倍数) 处吸收,因为光总是沿着y=x这条直线传播。所以如果光能经过那些传感器,传感器的坐标一定在(0,0)到 (maxnx, maxnx)之间, 即它们的坐标一定能化成(2kn±x, 2sm±y),满足2kn±x= 2sm±y,求出这个方程使2kn±x最小的解即可.具体用扩展欧几里得,求得k,然后让k化成最小,在求出2kn±x,即得解. 需要注意取模时要判断被取模的数是否为正.
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
long long n, m;
void exgcd(long long a, long long b, long long &d, long long &x, long long &y)
{
if(!b){d=a;x=1; y=0;}
else {exgcd(b, a%b, d, y, x); y-=x*(a/b); }
}
long long equation(long long a, long long b, long long c, long long &x, long long &y)
{
long long g;
exgcd(a,b,g,x,y);
if(c%g){ return -1;}
x*=c/g;
long long ran=b/g;
if(ran<0)ran=-ran;
x=(x%ran+ran)%ran; <span style="font-family: Arial, Helvetica, sans-serif;">//(a/g)*x+(b/g)*y=1;让x-b/g,y+a/g,等式仍成立, 所有x要最小只需对b/g取模即可,另外防止x是负数,所以还得再加一次b/g</span>
return 0;
}
long long que(long long x, long long y, long long maxn)
{
long long k, s;
if(equation(2*n, -2*m, y-x, k, s)==-1){return maxn+1;}
long long tx;
tx=2*k*n+x;
if(tx<0 || tx>maxn){ return maxn+1;}
return tx;
}
long long solve(long long x, long long y)
{
long long maxn=m*n;
long long res=maxn+1;
res=min(res, que(x, y, maxn)); //比较四种情况哪个解最小
res=min(res, que(x, -y, maxn));
res=min(res, que(-x, y, maxn));
res=min(res, que(-x, -y, maxn));
if(res==maxn+1)return -1; //若答案超过maxn,必然不能经过.
return res;
}
int main()
{
int k;
scanf("%lld%lld%d", &n, &m, &k);
int i;
for(i=0; i<k; i++)
{
long long x, y;
scanf("%lld%lld", &x, &y);
printf("%lld\n", solve(x,y));
}
return 0;
}