Description
抽象题意:有3个点在数轴上移动,每次移动可以把a点绕b转到a’,并且符合a~a’中无它点。
Solution
把3个点的位置用一个3元组来表示,(x,y,z) ,满足
x<y<z
,
(x,y,z)每轮的旋转有以下几种情况:
设
l=y−x,r−z−y
从里到外:
(x,y,z)~
(x−l,y−l,z)
,
(x,y,z)~
(x,y−r,z−r)
,
从外到里:
(x,y,z)~
(x+l,y+l,z)(l<r)
,
(x,y,z)~
(x,y−r,z−r)(l>r)
,
我们发现,这就是一棵树,
以从外到里为根,每轮不停向上跳,求LCA即可,
然而会超时 ,
把式子转化一下:
当l>r时,用可能因差距巨大,要不停的把x转过去,
然而这没有必要,因为每轮只是r=r-l,
所有我们可以一次性把r减到减不了为止,这样可以大大的减小时间,(与求gcd是类似)
分别求出目标和当前的层数后,先把目标和当前快跳到同一层,再枚举一个
2k
,看看两个点向上跳这么多后相不相同,
复杂度:
O(nlog(n))
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define FZA() a1=x,a2=y,a3=z
#define FZB() b1=x,b2=y,b3=z
#define OK() (q==x&&w==y&&e==z)
using namespace std;
typedef long long LL;
const int N=100500,maxlongint=2147483640;
int m,n,ans;
int a1,a2,a3,b1,b2,b3,a0,b0;
int x,y,z,s1,s2;
int jump(int q,int w,int e)
{
int l=w-q,r=e-w,s=0;
x=q,y=w,z=e;
if(r>l)
{
s=r/l;
if(r%l)r=r%l;else s--,r=l;
y=z-r;x=y-l;
return s;
}
s=l/r;
if(l%r)l=l%r;else s--,l=r;
y=x+l;z=y+r;
return s;
}
void jumpo(int q,int w,int e)
{
int l=w-q,r=e-w;
x=q,y=w,z=e;
if(r>l)r=r-l,y=z-r,x=y-l;
else l=l-r,y=x+l,z=y+r;
}
void jumpt(int q,int w,int e,int s1,int s2)
{
int t;
while(s1>s2)
{
t=jump(q,w,e);
if(s1-t<s2)break;
q=x,w=y,e=z;
s1-=t;
}
x=q,y=w,z=e;
if(s1>s2)
{
s1=s1-s2;
int l=w-q,r=e-w;
if(r>l)r=r-l*s1,y=z-r,x=y-l;
else l=l-r*s1,y=x+l,z=y+r;
}
}
int main()
{
int q,w,e,t;
scanf("%d%d%d%d%d%d",&a1,&a2,&a3,&b1,&b2,&b3);
if(a1>a2)swap(a1,a2);if(a1>a3)swap(a1,a3);if(a2>a3)swap(a2,a3);
if(b1>b2)swap(b1,b2);if(b1>b3)swap(b1,b3);if(b2>b3)swap(b2,b3);
x=a1,y=a2,z=a3;
while(y-x!=z-y)s1+=jump(x,y,z);
q=x,w=y,e=z;
x=b1,y=b2,z=b3;
while(y-x!=z-y)s2+=jump(x,y,z);
if(q!=x||w!=y||e!=z){printf("NO\n");return 0;}
if(!s1||!s2){printf("YES\n%d\n",s1+s2);return 0;}
ans+=abs(s1-s2);
jumpt(a1,a2,a3,s1,s2),FZA();
jumpt(b1,b2,b3,s2,s1),FZB();
s1=min(s1,s2);
t=1;
while(t*2<=s1)t<<=1;
while((a1!=b1||a2!=b2||a3!=b3)&&t)
{
while(s1<t)t/=2;
jumpt(a1,a2,a3,s1,s1-t);
q=x,w=y,e=z;
jumpt(b1,b2,b3,s1,s1-t);
if(!OK())
{
ans+=t*2;
s1-=t;
a1=q,a2=w,a3=e;
b1=x,b2=y,b3=z;
}
t/=2;
}
while(a1!=b1||a2!=b2||a3!=b3)jumpo(a1,a2,a3),FZA(),jumpo(b1,b2,b3),FZB(),ans+=2;
printf("YES\n%d\n",ans);
return 0;
}