The playground is a rectangle with walls around. Two balls are put in different positions inside the rectangle. The balls are so tiny that their volume can be ignored. Initially, two balls will move with velocity (1, 1). When a ball collides with any side of the rectangle, it will rebound without loss of energy. The rebound follows the law of refiection (i.e. the angle at which the ball is incident on the wall equals the angle at which it is reflected).
After they choose the initial position, Matt wants you to tell him where will the two balls collide for the first time.
For each test case, the first line contains two integers x and y. The four vertices of the rectangle are (0, 0), (x, 0), (0, y) and (x, y). (1 ≤ x, y ≤ 10 5)
The next line contains four integers x 1, y 1, x 2, y 2. The initial position of the two balls is (x 1, y 1) and (x 2, y 2). (0 ≤ x 1, x 2 ≤ x; 0 ≤ y 1, y 2 ≤ y)
In the second line, output “Collision will not happen.” (without quotes) if the collision will never happen. Otherwise, output two real numbers x c and y c, rounded to one decimal place, which indicate the position where the two balls will first collide.
3
10 10
1 1 9 9
10 10
0 5 5 10
10 10
1 0 1 10
Case #1:
6.0 6.0
Case #2:
Collision will not happen.
Case #3:
6.0 5.0
题目大意:
给了一个 x∗y 的矩阵,在这个矩阵中有两个小球(体积可以忽略):小球1 (x1,y1) , 小球2 (x2,y2) 现在这两个小球都以 (1,1) 的速度在运动,如果碰到边界会发生反弹(不损失能量),现在求两个小球第一次碰撞时的坐标。
解题思路:
我们可以将这个小球的运动在
x
轴 和
1)
x1=x2 and y1=y2
2)
x1=x2 and y1≠y2
3)
x1≠x2 and y1=y2
4)
x1≠x2 and x1≠y2
现在就四种情况分别进行讨论:
如果是第一种情况的话,第一次碰撞的点就是
(x1,y1) || (x2,y2)
如果是第二种情况的话,我们首先设在第一次碰撞的时间为
ty
,第一次碰撞的点为
(xp,yp)
那么就有 下图所示方程成立:
更正:对于图中的第二个式子有错误,应该是:
ty=yp−y1
然后可以解得:
ty = (2∗y−(y1+y2))2
,然后
(xp,yp)
就能确定了
同理,如果是第三种情况的话,我们可以解出
tx = (2∗x−(x1+x2))2
, 然后
(xp,yp)
也能确定了
如果是第四种情况的话就只需要加上一个周期就行了,对于
x
轴来说,
ty = (2∗y−(y1+y2))2+b∗y b:表示经过b个周期,周期为 y
然后又因为
tx = ty
, 然后联力两个方程组得到如下方程:
(2∗x−(x1+x2))2+a∗x=(2∗y−(y1+y2))2+b∗y
移项得:
a∗x−b∗y=(2∗y−(y1+y2))2−(2∗x−(x1+x2))2
这就是我们所常见的一元二次方程,然后扩展欧几里得一下求得
a
的最小正整数解就 OK 了。
需要注意的是,这里有一个小 trick:因为方程里有除法操作,所以我们先把所有的变量乘以 2,然后在操作就行了,还有就是 如果最后求得的解如果大于
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
inline LL GCD(LL a, LL b){
if(b == 0) return a;
return GCD(b, a%b);
}
void Exgcd(LL a, LL b, LL &x, LL &y){
if(b == 0){
x = 1, y = 0;
return;
}
LL x1, y1;
Exgcd(b, a%b, x1, y1);
x = y1;
y = x1 - (a/b)*y1;
}
int main()
{
int T; scanf("%d", &T);
for(int cas=1; cas<=T; cas++){
LL x, y, x1, x2, y1, y2;
scanf("%lld%lld%lld%lld%lld%lld", &x, &y, &x1, &y1, &x2, &y2);
x<<=1, y<<=1, x1<<=1, y1<<=1, x2<<=1, y2<<=1;
printf("Case #%d:\n",cas);
LL tx = (2*x-(x1+x2))/2, ty = (2*y-(y1+y2))/2;
if(x1==x2 && y1==y2) printf("%.1f %.1f\n", 0.5*x1, 0.5*y1);
else if(x1 == x2){
if(y1 > y2) swap(y1, y2);
x1 = (x1+ty)%(2*x), y1 = (y1+ty)%(y*2);
if(x1 > x) x1 = 2*x - x1;
if(y1 > y) y1 = 2*y - y1;
printf("%.1f %.1f\n", 0.5*x1, 0.5*y1);
}
else if(y1 == y2){
if(x1 > x2) swap(x1, x2);
x1 = (x1+tx)%(2*x), y1 = (y1+tx)%(y*2);
if(x1 > x) x1 = 2*x - x1;
if(y1 > y) y1 = 2*y - y1;
printf("%.1f %.1f\n", 0.5*x1, 0.5*y1);
}
else{
LL tp = ty - tx;
LL d = GCD(x, y);
if(tp % d) puts("Collision will not happen.");
else{
LL a = x / d, b = y / d, c = tp / d, xx;
Exgcd(a, b, xx, ty);
xx *= c;
xx = (xx%b+b)%b;
tx = tx + x*xx;
x1 = (x1+tx)%(2*x), y1 = (y1+tx)%(y*2);
if(x1 > x) x1 = 2*x - x1;
if(y1 > y) y1 = 2*y - y1;
printf("%.1f %.1f\n", 0.5*x1, 0.5*y1);
}
}
}
return 0;
}