CF724C: Ray Tracing
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF724C: Ray Tracing相关的知识,希望对你有一定的参考价值。
CF的题质量真心不低,这道题的标准解法(应该)是exgcd,打比赛的时候想到了具体的推导公式了,也意识到了需要用exgcd,但是因为寝室要锁门了(其实就是太弱,就放弃了。
首先很显然,这条线所经过的总时间应该是$lcm(N,M)$,其实这一点用处不大,但是如果想到了这一点,那么下一步就很好想出来,也就是这整个矩阵的射线轨迹是可以展开在一个$lcm(N,M) \\times lcm(N,M)$的矩阵上。到了这一步,只需要把矩形上的每个点铺开在矩阵上然后验证最近的一个点使得在展开的矩阵上横纵坐标相等。
现在问题就转换成了不断的对称一个矩形形成一个正方形,问矩形的每个点在正方形上的坐标。
在进一步就很好看出,对于原矩形上的点$(x,y)$,其在展开的矩形上的对称点应该是$(x \\pm (k \\times 2 \\times N),y \\pm (q\\times 2\\times N))$,
然后需要求的就是最小的$x \\pm (k \\times 2 \\times N)$使得$x \\pm (k \\times 2 \\times N)=y \\pm (q\\times 2\\times N)$
这个就可以用exgcd解决。
也就是用exgcd求$ax+by=c$的问题,简单说一下就是$a=N \\times 2$,而且$b=-M \\times 2$,$c=\\pm x \\pm y$,求解这四个方程的最小正整数解。
1 //CF 724C 2 //by Cydiater 3 //2016.10.9 4 #include <iostream> 5 #include <cstring> 6 #include <algorithm> 7 #include <queue> 8 #include <map> 9 #include <ctime> 10 #include <cmath> 11 #include <string> 12 #include <cstdio> 13 #include <queue> 14 #include <map> 15 using namespace std; 16 #define ll long long 17 #define up(i,j,n) for(ll i=j;i<=n;i++) 18 #define down(i,j,n) for(ll i=j;i>=n;i--) 19 inline ll read(){ 20 char ch=getchar();ll x=0,f=1; 21 while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} 22 while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 23 return x*f; 24 } 25 ll N,M,K,X,Y,ans,oo; 26 namespace solution{ 27 ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);} 28 void exgcd(ll a,ll b,ll &x,ll &y){ 29 if(b==0){x=1;y=0;return;} 30 exgcd(b,a%b,x,y); 31 ll t=x;x=y;y=t-a/b*y; 32 } 33 void equ(ll a,ll b,ll c,ll &x,ll &y){ 34 exgcd(a,b,x,y);ll d=gcd(a,b); 35 if(c%d!=0){x=oo;return;} 36 ll mod=abs(b/d); 37 x*=c/d; 38 x=((x%mod+mod)%mod+mod)%mod; 39 } 40 ll get(ll tx,ll ty){ 41 ll a=(N<<1),b=-(M<<1),c=ty-tx,x,y; 42 equ(a,b,c,x,y); 43 if(x==oo)return oo; 44 ll ans=2*x*N+tx; 45 if(ans<0||ans>=oo)return oo; 46 return ans; 47 } 48 void slove(){ 49 N=read();M=read();K=read();oo=N*M/gcd(N,M)+1; 50 up(i,1,K){ 51 X=read();Y=read(); 52 ans=oo; 53 ans=min(ans,get(X,Y)); 54 ans=min(ans,get(-X,Y)); 55 ans=min(ans,get(-X,-Y)); 56 ans=min(ans,get(X,-Y)); 57 if(ans==oo)ans=-1; 58 printf("%I64d\\n",ans); 59 } 60 } 61 } 62 int main(){ 63 //freopen("input.in","r",stdin); 64 using namespace solution; 65 slove(); 66 return 0; 67 }
以上是关于CF724C: Ray Tracing的主要内容,如果未能解决你的问题,请参考以下文章
CodeForece 724C Ray Tracing 扩展欧几里得
Ray Tracing The Next Week 超详解 光线追踪2-9
光追起步 Ray Tracing in One Weekend
Metal2剖析:基于MPS的GPU加速光线追踪(Accelerating Ray Tracing)