Solution
将图经过小学就学了的反转转化成一条斜率为 (1) 的直线,那么有解就是经过了 (a) 个 (n) 的同时经过了 (b) 个 (m) ,又因为起点 (S(x,y)) 也经过这条直线,所以 (y) 轴交点为 ((0,y-x)) 。
然后就可得到:
[an+(y-x)=bmRightarrow an-bm=x-yRightarrow an+b(-m)=x-y
]
用扩展欧几里得求解完,再 (\%) 出个最小值即可。
代码
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n,m,x,y,vx,vy;
int rex,rey;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
return x*f;
}
ll exgcd(ll a,ll b,ll &x1, ll &y1){
if(!b){
x1=1;
y1=0;
return a;
}
ll ans=exgcd(b,a%b,x1,y1);
ll t=x1;
x1=y1;
y1=t-a/b*y1;
return ans;
}
int main(){
n=read();m=read();x=read();y=read();vx=read();vy=read();
//判断平行情况
if(vx==0){
if(x==0||x==n){
if(vy==1) printf("%d %d
",x,m);
else printf("%d %d
",x,0);
}
else puts("-1");
return 0;
}
if(vy==0){
if(y==0||y==m){
if(vx==1) printf("%d %d
",n,y);
else printf("%d %d
",0,y);
}
else puts("-1");
return 0;
}
if(vx==-1) rex=1,x=n-x;
if(vy==-1) rey=1,y=m-y;
//这里就是将速度反转过来了
ll a,b,gcd;
gcd=exgcd(n,m,a,b);
if((x-y)%gcd){//判断无解
puts("-1");return 0;
}
a*=(x-y)/gcd,b*=(x-y)/gcd;//解出来的真正的a,b
int n1=n/gcd,m1=m/gcd;
ll a1=(a%m1+m1-1)%m1+1,b1=-((x-y)-a1*n)/m,ansx=n,ansy=m;//最小解
if(a1%2==0) ansx=n-ansx;//经过偶数个n,此时应该是0
if(b1%2==0) ansy=m-ansy;//经过偶数个m,此时应该是0
if(rex) ansx=n-ansx;//反转
if(rey) ansy=m-ansy;//反转
printf("%lld %lld
",ansx,ansy);
return 0;
}