题目大意:
有一个方形区域,四个角各有一个口袋,在(x,y)出有一小球,以Vx,Vy速度击出,碰到边界会像光路一样反
弹,问最先掉到哪个口袋里
分析:
其实问题的关键在于将反射线段利用光路的性质转换成一条直线,如下图
同时斜率为-1的情况实际上与斜率为1的直线第一次经过的顶点时对称的,所以为了方便起见,我们将直线都转换成斜率为1的直线,即如果输入的Vx=-1,我们需要将x=n-x(Vy=-1同理y=m-y),同时还能得到an+bm=c,进一步可以得到an+bm=x-y,最后就是用扩欧了,如果(x-y)%gcd(a,b)!=0输出-1,否则就用扩欧求得答案。
扩欧存在解时的讨论:如果a,b的个数为奇数,则通过的是(n,m);都为偶数时,则通过的是(0,0);a为奇,b为偶,则通过(n,0);a为偶,b为奇,则通过(0,m)。由此我们需要先求出a,b的奇偶性。这里我们要注意下,因为必定是需要第一块的,而且不一定在第一块里面就碰到顶点,所以在对a取模的时候应该_a=(a%_m+m-1)%m+1,将第一块先减去,最后再加回来。b可以直接根据a算出来,_b=-(x-y+_a*n)/m,在判断_a,_b的是奇数还是偶数。最后需要注意下,如果原本直线斜率为-1,扩欧得到的答案是对称过的点,我们还需要对称回去的,详细看代码
code:
#define debug
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
const int maxn=1e5;
const int INF=0x3f3f3f3f;
const int inf=0x7fffffff;
const int mod=1e9+7;
const int MOD=10007;
//----
//define
int n,m,x,y,vx,vy;
//exgcd
ll exgcd(int a,int b,ll &x,ll &y) {
if(b==0) {
x=1;
y=0;
return a;
} else {
ll tmp=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return tmp;
}
}
//gcd
ll gcd(ll a,ll b) {
return b==0?a:gcd(b,a%b);
}
//solve
void solve() {
while(cin>>n>>m>>x>>y>>vx>>vy) {
//vx=0,vy=0的这两种情况可以直接判断掉
if(!vx) {
if(x==0||x==n) {
if(vy>0)cout<<x<<" "<<m<<endl;
else cout<<x<<" "<<0<<endl;
} else {
cout<<-1<<endl;
}
continue;
}
if(!vy) {
if(y==0||y==m) {
if(vx>0)cout<<n<<" "<<y<<endl;
else cout<<0<<" "<<y<<endl;
} else {
cout<<-1<<endl;
}
continue;
}
//----------------------------------------
int rx=0,ry=0;
ll a,b,d=exgcd(n,m,a,b);
//关于x=y轴对称
if(vx==-1){
rx=1;
x=n-x;
}
//关于y=x轴对称
if(vy==-1){
ry=1;
y=m-y;
}
ll k=x-y;
//无解的情况
if(k%d){
cout<<-1<<endl;
continue;
}
k/=d;
a*=k;b*=k;
ll _n=n/d,_m=m/d;
ll _a=(a%_m+_m-1)%_m+1,_b=-((x-y)-_a*n)/m;
ll ansx=n,ansy=m;
if(a%2==0)ansx=n-ansx;
if(_b%2==0)ansy=m-ansy;
if(rx)ansx=n-ansx;
if(ry)ansy=m-ansy;
cout<<ansx<<" "<<ansy<<endl;
}
}
int main() {
ios_base::sync_with_stdio(0);
#ifdef debug
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
cin.tie(0);
cout.tie(0);
solve();
return 0;
}