题意:在一个n*m的矩形中有k个点,给出这k个点的坐标。 有一个栗子从(0,0)点直线射入,1s后到达(1,1)点。碰到矩形内壁会反弹(反弹中入射角等于反射角)。问对于这k个点,栗子分别在什么时间经过,不能经过输出-1.
题解:膜了好几个dalao的写法,没有看懂怎么模拟的。大致说一下exgcd的思路吧,我们可以把这个矩形展开,让栗子在矩形中反射的路线变成一条直线。 在展开的过程中 对于每个点都有对应的通式(2kn±x , 2sm±y),然后计算出最小的 2kn±x就可以了。 注意:我们首先要计算出栗子反射碰到矩形的四个角射出矩形的时间temp,
要求 2kn±x<temp, 否则表示该点不会被栗子经过。
不是很懂exgcd的求解过程啊,暑假又白看了,人蠢就不应该看数论,QAQ。。。。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
const LL INF=2e18;
int n,m,k;
void exgcd(LL a,LL b,LL &d,LL &x,LL &y)
{
if(b==0){
x=1; y=0;
d=a;
return ;
}
else{
exgcd(b,a%b,d,y,x);
y-=(a/b)*x;
}
}
LL solve(int x,int y)
{
LL N=2*n,M=2*m;
LL X,Y,d;
exgcd(N,M,d,X,Y);
if((y-x)%d!=0)
return INF;
LL lcm=1ll*N*M/d;
X*=(y-x)/d;
LL x0=X%lcm*N%lcm+x;
x0=(x0%lcm+lcm)%lcm;
if(x0==0) x0+=lcm;
return x0;
}
int main()
{
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
LL temp=min( { solve(0,0), solve(n,0), solve(0,m), solve(n,m) } );
while(k--)
{
int x,y;
scanf("%d%d",&x,&y);
LL tim=min({solve(x,y),solve(2*n-x,y),solve(x,2*m-y),solve(2*n-x,2*m-y)});
if(tim<temp&&tim<INF)
printf("%I64d\n",tim);
else
printf("-1\n");
}
}
return 0;
}