Description
两个质点在一个x*y的矩形区域内,初始位置(x1,y1)和(x2,y2)给出,两个质点保持(1,1)的速度运动,遇到区域边界会反弹(满足反射定律),问两个质点第一次相遇的位置,如果不会相遇则输出Collision will not happen.
Input
第一行为一整数T表示用例组数,每组用例第一行为两个整数x和y表示区域规格,第二行四个整数x1,y1,x2,y2分别表示两个质点的初始位置
Output
如果两个质点会相遇则输出第一次相遇的位置,否则输出Collision will not happen.
Sample Input
3
10 10
1 1 9 9
10 10
0 5 5 10
10 10
1 0 1 10
Sample Output
Case #1:
6.0 6.0
Case #2:
Collision will not happen.
Case #3:
6.0 5.0
Solution
两个质点如果相遇那么一定在整点或者半点处,所以首先将所有数据乘2避免小数出现,设第一次两点横坐标相同的时刻为tx,若x1=x2则任意时刻两质点横坐标相同,若x1!=x2,那么有(x1+tx)%x=(x2+tx)%x且((x1+tx)/x)%2!=((x2+tx)/x)%2(横坐标不同时两点相遇前碰撞次数一定不同),由上式可以很快求出tx=(2*x-(x1+x2))/2,那么两质点横坐标相同的时刻就是tx+k*x,同理可以求出ty表示第一次两质点纵坐标相同的时刻,那么第一次两质点相遇的时刻T=tx+k1*x=ty+k2*y,即k1*x=ty-tx(mod y),问题转化为求该一元线性同余方程的解
Code
#include<cstdio>
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
ll x1,y1,x2,y2,x,y;
ll extend_gcd(ll a,ll b,ll &x,ll &y)
{
ll d=a;
if(b!=0)
{
d=extend_gcd(b,a%b,y,x);
y-=(a/b)*x;
}
else
{
x=1;
y=0;
}
return d;
}
ll linear(ll a,ll b,ll c)//求解一元线性同余方程ax=b(mod c)
{
ll x,y;
ll g=extend_gcd(a,c,x,y);
if(b%g)//无解
return -1;
x=x*(b/g);
ll mod=c/g;
x=(x%mod+mod)%mod;
return x;
}
ll solve()
{
ll fx,fy,tx,ty;
fx=(x1==x2),fy=(y1==y2);
tx=(2*x-(x1+x2))/2,ty=(2*y-(y1+y2))/2;
if(fx&&fy)return 0;
if(fx)return ty;
if(fy)return tx;
ll ans=linear(x,ty-tx,y);
if(ans==-1)return INF;
return tx+ans*x;
}
int main()
{
int T,res=1;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld%lld%lld%lld%lld",&x,&y,&x1,&y1,&x2,&y2);
x*=2,y*=2,x1*=2,y1*=2,x2*=2,y2*=2;
ll t=solve();
printf("Case #%d:\n",res++);
if(t==INF)printf("Collision will not happen.\n");
else
{
ll xx=t+x1,yy=t+y1;
if((xx/x)%2==0)xx%=x;
else xx=((x-xx)%x+x)%x;
if((yy/y)%2==0)yy%=y;
else yy=((y-yy)%y+y)%y;
printf("%.1lf %.1lf\n",xx/2.0,yy/2.0);
}
}
return 0;
}