这道题太神了 像我这种蒟蒻的脑瓜哪里能想出来QAQ….
我们可以发现其实最多只有3种跳的方法 中间往外跳2种 左右往中间跳 1种或没有(等距的时候就没有了)
其实左右往中间跳之后 又能以往外跳跳到原状态 其实就是一个二叉树 往中间跳就是父亲状态 往外跳就是左右孩子状态
所以看看初始状态和末状态是否在一颗树上就能判断有解还是无解
关于怎么跳 可以用一种类似gcd的方法(复杂度log)
令a=y-x,b=z-y 若 a< b可以直接跳到 a,b-a
反之同理 以此类推 (a,b)->(a%b,b)或(a,b%a) GCD!
最后我用了二分的方法确定lca。
代码借鉴了一下别人的 感觉很简洁清晰明了啊~
#include<bits/stdc++.h>
using namespace std;
const int inf=1e9;
inline int read()
{
char ch=getchar(); int x=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();}
return x*f;
}
struct node{
int x,y,z;
void init(){
x=read(),y=read(),z=read();
if(x>y)swap(x,y); if(x>z)swap(x,z); if(y>z)swap(y,z);
}
bool operator==(node o)const{return x==o.x&&y==o.y&&z==o.z;}
}a,b,p,q;
int len,k;
node getfa(node t,int dep){
for(len=0;dep;len+=k){
int u=t.y-t.x,v=t.z-t.y;
if(u==v)return t;
if(u<v){
k=min((v-1)/u,dep);
t.x+=k*u,t.y+=k*u,dep-=k;
}
else{
k=min((u-1)/v,dep);
t.y-=k*v,t.z-=k*v,dep-=k;
}
}
return t;
}
int main()
{
a.init(),b.init(); int l1,l2;
p=getfa(a,inf),l1=len,q=getfa(b,inf),l2=len;
if(p==q); else {printf("NO\n"); return 0;}
if(l1<l2)swap(a,b),swap(l1,l2);
a=getfa(a,l1-l2);
int l=0,r=l2,mid,ans;
while(l<=r){
mid=(l+r)>>1;
if(getfa(a,mid)==getfa(b,mid))ans=mid,r=mid-1; else l=mid+1;
}
printf("YES\n%d\n",(ans<<1)+l1-l2);
return 0;
}