Input
Sample Input
1 2 3 0 3 5 Output
Sample Output
YES 2
Data Constraint
现在有A,B,C三个点,位置分别在x,y,z每一次我们可以进行下列的一项操作,将位置变为: 1:(x,x-(y-x),z) 2:(x,z+(z-y),z) 3:(y+(y-x),y,z)并且此时新的x位置要在z的前面,否则不能这样动 4:(x,y,z-(y-x))并且此时新的位置要在x的后面,否则不能这样动 现在给出初始位置和目标位置,求所需要的最短的步数(不一定要到对应的位置,只要xyz都到了三个目标位置的其中一个就可以了)
好难啊(╯‵□′)╯只会暴力
这一题可以转化成一个树的模型并且求解,我们可以发现上面3,4两种转换方式只有一种是可行的,那么不妨把这种转换设为当前状态的父亲,同理,1,2两种状态设为当前状态的儿子。我们可以发现,对于任意一个三元组(x,y,z( x<y<z )),如果一直进行3,4操作,那么到最后一定会两种操作都进行不了(y-x=z-y)我们可以把这个状态设为这个三元组所在树的树根。当起始三元组和目标三元组到根都不相等时,那么这两个三元组就不在一棵树上,也就不可能转换为彼此了。 我们可以先把两个三元组都往根跑一遍,顺便得出深度,然后再二分一下,就可以得出两个三元组相交时的深度了,这个方法可以拿40分(居然才给40分QAQ) 我们发现,上面的方法时间主要损耗在往根跑的时候,举个例子(1,2,10000000)这种情况要跳很多次,而且没有意义,为了解决这个问题,我们设t1=y-x,t2=z-y;当 t1<t2 时显然可以往右边跳(t2-1)/t1(下取整)次,当t1>t2时也是一样的,那么我们就可以一次可以跳很多步了。(注意不能跳到二分深度的上面去了,要判断一下)
一堆注释2333
const n=3; var a,b,c:array[0..5]of longint; i,j,k,l,r,x,y,z,deep1,deep2,mid:longint; bz:boolean; function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end; function max(x,y:longint):longint; begin if x>y then exit(x) else exit(y); end; procedure work1(p:longint); var i,j,k,l,r:longint; begin l:=y-x; r:=z-y; if l=r then exit; if l<r then begin k:=(r-1) div l; if p-k<mid then k:=p-mid; p:=p-k; //if k>p then k:=p; //p:=p-k; x:=x+k*l; y:=y+k*l; if bz=false then deep1:=deep1+k; end else begin k:=(l-1) div r; if p-k<mid then k:=p-mid; p:=p-k; //if k>p then k:=p; //p:=p-k; y:=y-k*r; z:=z-k*r; if bz=false then deep1:=deep1+k; end; if p>mid then work1(p); end; procedure work2(p:longint); var i,j,k,l,r:longint; begin l:=y-x; r:=z-y; if l=r then exit; if l<r then begin k:=(r-1) div l; if p-k<mid then k:=p-mid; p:=p-k; //if k>p then k:=p; //p:=p-k; x:=x+k*l; y:=y+k*l; if bz=false then deep2:=deep2+k; end else begin k:=(l-1) div r; if p-k<mid then k:=p-mid; p:=p-k; //if k>p then k:=p; //p:=p-k; y:=y-k*r; z:=z-k*r; if bz=false then deep2:=deep2+k; end; if p>mid then work2(p); end; procedure init; begin for i:=1 to n do read(a[i]); for i:=1 to n-1 do for j:=i+1 to n do if a[i]>a[j] then begin a[0]:=a[i]; a[i]:=a[j]; a[j]:=a[0]; end; for i:=1 to n do read(b[i]); for i:=1 to n-1 do for j:=i+1 to n do if b[i]>b[j] then begin b[0]:=b[i]; b[i]:=b[j]; b[j]:=b[0]; end; x:=a[1]; y:=a[2]; z:=a[3]; work1(maxlongint); c[1]:=x; c[2]:=y; c[3]:=z; x:=b[1]; y:=b[2]; z:=b[3]; work2(maxlongint); if (c[1]<>x) or (c[2]<>y) or (c[3]<>z) then begin writeln('NO'); halt; end; writeln('YES'); l:=0; //if deep1=0 then deep1:=1; //if deep2=0 then deep2:=1; //dec(deep1); dec(deep2); r:=min(deep1,deep2); bz:=true; end; begin init; while l<r do begin mid:=(l+r) div 2; x:=a[1]; y:=a[2]; z:=a[3]; work1(deep1); c[1]:=x; c[2]:=y; c[3]:=z; x:=b[1]; y:=b[2]; z:=b[3]; work2(deep2); if (c[1]=x) and (c[2]=y) and (c[3]=z) then l:=mid+1 else r:=mid; end; //l:=min(deep1,deep2)-l; //l:=mid; r:=mid; mid:=max(l,mid); x:=a[1]; y:=a[2]; z:=a[3]; work1(deep1); c[1]:=x; c[2]:=y; c[3]:=z; x:=b[1]; y:=b[2]; z:=b[3]; work2(deep2); if (c[1]=x) and (c[2]=y) and (c[3]=z) then l:=mid else l:=mid-1; writeln(abs(l-deep1)+abs(l-deep2)); end.