题意:平面n*m的空间有两个点在(x1,y1),(x2,y2) 向(1,1)运动,遇到边界反弹,最早在哪一点相遇。
分析 (1)答案只可能在整点或.5点,讲所有的数据先乘2;
(2) 只考虑x i) 若x1=x2 则 x1与x2在任意时刻都相同,ii)否则x1+t与x2+t 当(x1+t+x2+t)% n=0 且(((x1+t)/n)%2!=((x2+t)/n)%2)
(3) 所以可以快速的求出最小的tx,每一次相遇的时间是 tx+a*n
同理求出最小的ty,每一次相遇的时间是 ty+b*m
(4) T=tx+a*n=ty+b*m =>a*n-b*m=ty-tx 中国剩余定理求出T
<span style="font-family:SimHei;">#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<stdlib.h>
using namespace std;
#define maxn 1000
int n,m;
int x1,y1,x2,y2;
typedef long long ll;
ll exgcd(ll a,ll b,ll &x,ll &y){
ll d=a;
if(b!=0){d=exgcd(b,a%b,y,x);y-=(a/b)*x;}
else x=1,y=0;
return d;
}
const ll INF=1LL<<60;
ll solve(){
scanf("%d%d",&n,&m);
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
n*=2;m*=2;x1*=2;y1*=2;x2*=2;y2*=2;
bool txx=0,tyy=0;
int tx,ty;
if(x1==x2) txx=1; if(y1==y2) tyy=1;
tx=(n*2-(x1+x2))/2; ty=(m*2-(y1+y2))/2;
if(txx&&tyy) return 0;
if(txx) return ty;
if(tyy) return tx;
ll a,b;
ll d=exgcd(n,m,a,b); //a*n-b*m=ty-tx
if((ty-tx)%d!=0) return INF;
if(a<0) a+=m/d;
ll T=a*(ty-tx)/d*n+tx;
T=T%(n/d*m);
if(T<0) T+=(n/d*m);
return T;
}
int main(){
int t,cas=1;
scanf("%d",&t);
while(t--){
ll T=solve();
printf("Case #%d:\n",cas++);
if(T==INF) printf("Collision will not happen.\n");
else{
ll x=T+x1;
ll y=T+y1;
if((x/n)%2==0) x=x%n;
else x=((n-x)%n+n)%n;
if((y/m)%2==0) y=y%m;
else y=((m-y)%m+m)%m;
printf("%.1f %.1f\n",x/2.0,y/2.0);
}
}
}</span>