CF724C Ray Tracing 扩展欧几里得 平面展开
LINK:Ray Tracing
虚这道题很久了 模拟赛考了一个加强版的 瞬间就想到了这道简化版的。
考虑做法 暴力模拟可能可以 官方正解好像就是这个。
不过遇到这种平面问题可以考虑把平面给无限的展开。
考虑展开之后点的坐标的通项 2kn +/- x 2km +/- y.
这个可以画图发现 那么就可以得到4个方程。
暴力解开 考虑遇到四个角就停止的问题 那么这个值必须要小于LCM(n,m).
显然 同时要保证合法的话需要>0.
容易发现方程只需要解一次 所以复杂度为 k+logn.
(真是ex死我了
ll n,m,k;
ll lcm,g,maxx;
ll xx,yy,ww;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void exgcd(ll a,ll b)
{
if(!b){xx=1,yy=0;ww=a;return;}
exgcd(b,a%b);
ll z=xx;xx=yy;yy=z-a/b*yy;
return;
}
inline ll solve(ll x,ll y)
{
ll c=y-x;
if(c%ww)return -1;
ll b=-m/ww;
c/=ww;b=abs(b);
ll w1=(xx*c%b+b)%b;
ll ans=n*w1+x;
return ans<=0||ans>=lcm?-1:ans;
}
signed main()
{
freopen("1.in","r",stdin);
n=read();m=read();k=read();
g=gcd(n,m);lcm=n*m/g;
n=n*2;m=m*2;
exgcd(n,-m);
for(ll i=1;i<=k;++i)
{
ll w,x,y;maxx=INF;
x=read();y=read();
if(!x&&!y){printf("0\n");continue;}
w=solve(x,y);if(w!=-1)maxx=min(maxx,w);
w=solve(x,-y);if(w!=-1)maxx=min(maxx,w);
w=solve(-x,y);if(w!=-1)maxx=min(maxx,w);
w=solve(-x,-y);if(w!=-1)maxx=min(maxx,w);
printf("%lld\n",maxx==INF?-1:maxx);
}
return 0;
}