在n*m的方格的两个整数点处发射初速度都为(1, 1)的质点,质点在边界会发生弹性碰撞,问两质点能否相遇。若能,求出二者第一次相遇的坐标。
首先为了避免小数的出现,将坐标全部扩大为原来的两倍。
这种碰撞问题显然需要将速度正交分解,然后有四种情况:
(1)x1==x2&y1==y2 此时显然t=0。
(2)x1==x2&&y1 != y2 此时显然结果取决于不相等的y,经过推导可以得出相遇的t = m - (y1+y2)/2。
(3)x1 != x2&&y1==y2 同上,t = n - (x1+x2)/2。
(4)x1 != x2 && y1 != y2 这个时候不能在一个周期里相遇,根据(2)(3)的结果,此时就应该是:
m - (y1 + y2)/2 + x*m = n - (x1 + x2)/2 * y*n
对于这个一元线性同余方程,可以用扩展欧几里得得到它的解,需要注意的是这里需要的是它的最小非负整数解。
显然无解的情况就是( (m - (y1+y2)/2) - (n - (x1+x2)/2) % gcd(n, m) != 0)。
最后用求出的时间算出在坐标范围内的最终坐标然后恢复到二分之一即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
typedef long long ll;
using namespace std;
const int maxn = 200050;
int t;
ll n, m, xa, xb, ya, yb;
ll ex_gcd(ll a,ll b, ll &x, ll &y)
{
if(b == 0) {x = 1, y = 0; return a;}
ll d = ex_gcd(b, a%b, y, x);
y -= a/b*x;
return d;
}
int main()
{
scanf("%d", &t);
int kase = 0;
while(t--)
{
scanf("%lld%lld", &n, &m);
scanf("%lld%lld%lld%lld", &xa, &ya, &xb, &yb);
printf("Case #%d:\n", ++kase);
xa <<= 1, xb <<= 1, ya <<= 1, yb <<= 1, n <<= 1, m <<= 1;
ll ans = -1, ta = n - (xa+xb)/2, tb = m - (ya+yb)/2;
if(xa == xb && ya == yb) ans = 0;
if(ya == yb && xa != xb) ans = ta;
if(xa == xb && ya != yb) ans = tb;
if(xa != xb && ya != yb)
{
ll x, y;
ll d = ex_gcd(n, m, x, y);
ll tmp = tb - ta;
if(tmp % d != 0) ans = -1;
else
{
x *= (tmp/d);
x =(x%(m/d) + (m/d)) % (m/d);
ans = ta + n*x;
}
}
if(ans == -1) puts("Collision will not happen.");
else
{
xa = (xa + ans) % (n*2);
ya = (ya + ans) % (m*2);
if(xa > n) xa = 2*n - xa;
if(ya > m) ya = 2*m - ya;
printf("%.1lf %.1lf\n", xa/2.0, ya/2.0);
}
}
return 0;
}