题意:给出俩球的初始坐标(x1,y1)、(x2,y2),两个球都是往(1,1)方向运动,如果遇到墙壁,两个球会满足反射定律反射,问最后两球相遇的坐标
思路:设相遇经历的时间为t
1、如果两球的初始坐标相同,那么相遇时间t=0
2、如果两球的初始横坐标相同,那么在x方向两球是相对静止的,所以只需要考虑y方向,假设y1<y2,那么y1+t=m-(y2+t-m),那么t=m-(y1+y2)/2
3、如果两球的初始纵坐标相同,同理在y方向两球是相对静止的,所以只考虑x方向,相对应t=n-(x1+x2)/2
4、如果两球的初始的横纵坐标都不相同,由于两球横坐标相同的周期是n,所以t=n-(x1+x2/2+n*k1,两球纵坐标相同的周期是m,所以t=t=m-(y1+y2)/2+m*k2,两个t相等,那么
n-(x1+x2)/2+n*k1=m-(y1+y2)/2+m*k2,也就是
n*k1-m*k2=m-(y1+y2)/2-(n-(x1+x2)/2)
我们想通过求k1、k2来求时间t,所以可以用exgcd来做
要求k1是正的、k2是负的,所以求最小的正k1对应的t就可以了
exgcd需要整数,但过程中会遇到/2的情况,所以事先所有的点都乘2
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long gcd(long long a,long long b)
{
if(b==0) return a;
else gcd(b,a%b);
}
void ex_gcd(long long a,long long b,long long &x,long long &y)
{
if(b==0)
{
x=1;
y=0;
return ;
}
long long x1,y1;
ex_gcd(b,a%b,x1,y1);
x=y1;
y=x1-(a/b)*y1;
}
int main()
{
long long T;
scanf("%lld",&T);
long long cnt=0;
while(T--)
{
cnt++;
long long n,m;
long long x1,x2,y1,y2;
scanf("%lld%lld",&n,&m);
scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
n*=2;m*=2;x1*=2;y1*=2;x2*=2;y2*=2;
long long p=n-(x1+x2)/2;
long long q=m-(y1+y2)/2;
long long t;
if(x1==x2&&y1==y2)
t=0;
else if(x1==x2&&y1!=y2)
t=q;
else if(y1==y2&&x1!=x2)
t=p;
else
{
long long x,y;
long long a,b,c,d;
a=n;
b=m;
d=gcd(a,b);
c=q-p;
if(c%d!=0)
{
printf("Case #%lld:\nCollision will not happen.\n",cnt);
continue;
}
else
{
a/=d;
b/=d;
c/=d;
ex_gcd(a,b,x,y);
x=x*c;
y=y*c;
x=(x%b+b)%b;
y=(y%a+a)%a;
t=p+n*x;
}
}
x1=((x1+t)%(2*n));
if(x1>n) x1=2*n-x1;
y1=((y1+t)%(2*m));
if(y1>m) y1=2*m-y1;
printf("Case #%lld:\n%.1f %.1f\n",cnt,x1/2.0,y1/2.0);
}
return 0;
}