【文文殿下】【CF724C】Ray Tracing (中国剩余定理)

时间:2023-03-10 02:49:22
【文文殿下】【CF724C】Ray Tracing (中国剩余定理)

题解

我们考虑将棋盘扩大一倍,这样相当于取膜。然后,我们只要对x,y,的位置分类讨论,做四次crt就行。具体细节看文文代码。

#include<cstdio>
#include<algorithm>
typedef long long ll;
const ll inf = 1000000000000LL;
int a[10],m[10];
inline ll exgcd(ll a,ll b,ll &x,ll &y) {
if(b==0) {
x=1;y=0;
return a;
}
ll d = exgcd(b,a%b,x,y);
ll tmp = x;
x=y;
y=tmp-a/b*y;
return d;
}
inline ll China() {
ll A=a[1],M=m[1],k,y;
for(int i = 2;i<=2;++i) {
ll d = exgcd(M,m[i],k,y),mod=(m[i]/d),c=a[i]-A;
if(c%d) return inf;
k=(k*c/d%mod+mod)%mod;
A+=k*M;M*=m[i]/d;A=(A+M)%M;
}
return A;
}
inline ll solve(ll x,ll y) {
a[1]=x;
a[2]=y;
return China();
}
int aa,bb,k;
int main() {
//freopen("test.in","r",stdin);
scanf("%d%d%d",&aa,&bb,&k);
while(k--) {
m[1]=2*aa;
m[2]=2*bb;
int x,y;
scanf("%d%d",&x,&y);
ll ans = inf;
ans=std::min(ans,solve(x,y));
ans=std::min(ans,solve(x,m[2]-y));
ans=std::min(ans,solve(m[1]-x,y));
ans=std::min(ans,solve(m[1]-x,m[2]-y));
if(ans==inf) puts("-1");
else printf("%lld\n",ans);
}
return 0;
}