P5088 矩形
思路
将原图逆时针旋转
考虑到直接模拟光路较为复杂,我们可以建立如图所示的镜像单元格。
容易证明,图中同色线段长度相等。
于是问题就转换为:求直线第一次到达形如
由于
设直线第一次到达的点为
由于
容易证明,
我们回到
注意以下两点:
-
在开始时要先化简。令
g_1 = \gcd(n,m) ,g_2 = \gcd (a,b) ,并使n \gets \displaystyle{\frac{n}{g_1}} ,m \gets \displaystyle{\frac{m}{g_1}} ,a \gets \displaystyle{\frac{a}{g_2}} ,b \gets \displaystyle{\frac{b}{g_2}} 。 -
特判
a=0 或b=0 的情况。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,a,b;
inline int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')ret=ret*10+(ch&15),ch=getchar();
return ret*f;
}
int gcd(int x,int y){
return y?gcd(y,x%y):x;
}
int solve(int n,int m,int a,int b){
if(!a||!b)return 0;
int g1=gcd(n,m),g2=gcd(a,b);
n/=g1,m/=g1,a/=g2,b/=g2;
int g=gcd(a*m,b*n);
int k1=b*n/g,k2=a*m/g;
return k1+k2-2;
}
signed main(){
n=read(),m=read(),a=read(),b=read();
printf("%lld\n",solve(n,m,a,b));
return 0;
}