题目重点是每次不能跳过两个棋子

即对于每一个棋子的状态(a,b,c) (a<b<c)

最多有两种移动的方式

1.中间往两边跳 (a,b,c)-->(2b-a,a,c)或(a,c,2b-c)

2.a或c往中间跳 当然要满足不跳过两个棋子

b-a<c-b a可以跳过b (a,b,c)-->(b,2b-a,c)

c-b<b-a c可以跳过b (a,b,c)-->(a,2b-c,b)

当然当c-b=b-a时就不能再往中间跳了

此时可以想到对于一个状态(a,b,c)如果一直往中间跳 最终的状态一定是一定的

于是可以把这个最终的状态看做是根节点 中间向左向右跳的状态分别是左右节点

这样就是一棵二叉树了,而询问两个状态能否相互跳到就是树上距离了

于是回顾lca求树上距离的过程,我们首先要确定一个状态的k层祖先的状态是什么

如果暴力跳的话就会超时,所以我们想一种特殊的情况

(1,100000000,100000001) 显然暴力跳会一直跳1的长度是不行的

但我们看这时b-a很大但c-b很小就意味着接下来会很多次都是c往b跳

能跳几次呢?因为棋子实际上没有区别 假如c跳过b 那么实际上就是c和b一起向左平移了c-b的距离

所以c往b跳的次数就是(b-a)/(c-b)

这样对于本题就可以达到取模gcd的速度快速求出一个状态的k层祖先状态

这样用lca的手法先让两点到达同一高度,再二分一个距离k,如果两种状态的k层祖先一直 则将k缩小,反之增大求出他们的最近公共祖先

#include<bits/stdc++.h>
using namespace std;
int ans,a,b,c,x,y,z,x1,yy1,z1,a1,b1,c1,t1,t2;
int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(x=x*10+ch-48,ch=getchar(),ch>='0'&&ch<='9');
return x*f;
}
void SWAP(int &a,int &b,int &c){if(a>b){swap(a,b);if(a>c)swap(a,c);}if(b>c)swap(b,c);}
void back(int &a,int &b,int &c,int k)//将状态a,b,c回到k步前的状态 即它的k层祖先
{
int A=b-a,B=c-b;
if(A<B)
{
int t=B/A;if(B%A==0)t--;
if(t>=k){a=a+k*A;b=b+k*A;}
else {a=a+t*A;b=b+t*A;back(a,b,c,k-t);}
}else
{
int t=A/B;if(A%B==0)t--;
if(t>=k){c=c-k*B;b=b-k*B;}
else {c=c-t*B;b=b-t*B;back(a,b,c,k-t);}
}
}
int getfa(int &a,int &b,int &c)//寻找状态a,b,c的根节点
{
int A=b-a,B=c-b;
if(A==B)return 0;
if(A<B)
{
int t=B/A;if(B%A==0)t--;
a=a+t*A;b=b+t*A;
return t+getfa(a,b,c);
}else
{
int t=A/B;if(A%B==0)t--;
c=c-t*B;b=b-t*B;
return t+getfa(a,b,c);
}
}
int comp(int a,int b,int c,int x,int y,int z){if(a==x&&b==y&&c==z)return 1;else return 0;}
int main()
{
a=read();b=read();c=read();
x=read();y=read();z=read();
SWAP(a,b,c);SWAP(x,y,z);
x1=x;yy1=y;z1=z;a1=a;b1=b;c1=c;
t1=getfa(x1,yy1,z1);t2=getfa(a1,b1,c1);
if(!comp(x1,yy1,z1,a1,b1,c1)){puts("NO");return 0;}
if(t1<t2) back(a,b,c,t2-t1);else back(x,y,z,t1-t2);
int l=0,r=min(t1,t2);
while(l<=r)
{
int mid=(l+r)>>1;
x1=x;yy1=y;z1=z;a1=a;b1=b;c1=c;
back(x1,yy1,z1,mid);back(a1,b1,c1,mid);
if(comp(a1,b1,c1,x1,yy1,z1)) ans=mid,r=mid-1;else l=mid+1;
}
puts("YES");
printf("%d",2*ans+max(t2,t1)-min(t2,t1));
return 0;
}
/*
(a,b,c) if b-a<c-b --> (b,2b-a,c)
if c-b<b-a --> (a,2b-c,b) */

[luogu]P1852跳跳棋的更多相关文章

  1. P1852 跳跳棋 [LCA思想+二分答案]

    题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有\(3\)颗棋子,分别在\(a,b,c\)这三个位置.我们要通过最少的跳动 ...

  2. 【题解】P1852 跳跳棋

    link 题意 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.棋盘上有3颗棋子,分别在 \(a,b,c\) 这三个位置.我们要通过最少的跳动把他们的位置移动成 \(x,y, ...

  3. 洛谷 P1852 [国家集训队]跳跳棋 解题报告

    P1852 [国家集训队]跳跳棋 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在\(a\),\(b\), ...

  4. P1852 [国家集训队]跳跳棋

    P1852 [国家集训队]跳跳棋 lca+二分 详细解析见题解 对于每组跳棋,我们可以用一个三元组(x,y,z)表示 我们发现,这个三元组的转移具有唯一性,收束性 也就是说,把每个三元组当成点,以转移 ...

  5. 洛谷 P1852 [国家集训队] 跳跳棋

    题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动 ...

  6. 【洛谷】1852:[国家集训队]跳跳棋【LCA】【倍增?】

    P1852 [国家集训队]跳跳棋 题目背景 原<奇怪的字符串>请前往 P2543 题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个 ...

  7. 【LCA】bzoj 2144:跳跳棋

    2144: 跳跳棋 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 248  Solved: 121[Submit][Status][Discuss] ...

  8. bzoj2144 【国家集训队2011】跳跳棋

    Description 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他 ...

  9. 跳跳棋(9018_1563)(BZOJ_2144)

    题目: Hzwer的跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 某一天,黄金大神和cjy用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.他们要 ...

随机推荐

  1. PCB 布线,直角线,差分线,蛇形线

    1.直角线 直角走线的一般标准是PCB布线中要尽量避免的情况,也几乎成为衡量布线好坏的标准之一. 直角走线对信号的影响主要体系那在下面三个方面 1.保教可以等效为传输线是哪个的容性负载,减缓上升时间. ...

  2. 常用正则表达式爬取网页信息及HTML分析总结

    Python爬取网页信息时,经常使用的正则表达式及方法. 1.获取<tr></tr>标签之间内容 2.获取<a href..></a>超链接之间内容 3 ...

  3. Top 5 Reasons to Get BMW ICOM A2 with Latest Software

    Top 5 Reasons to Get BMW ICOM A2 with Latest Software 1.BMW ICOM A2 Hardware Version: V2018.03 2.Sup ...

  4. javaweb笔记06—(页面跳转及编码格式)

    1.指令:<%@     %>:一个页面可以有多个import, 但是标识本页面为jsp页面的指令只能是一条(建议是一条 ) 2.出错页面:<%@ isError(true)%> ...

  5. 使用准现网的数据,使用本地的样式脚本,本地调试准现网页面(PC适用)

    原理: 本地逻辑,重新渲染 步骤: 1.安装插件:Tampermonkey 度盘:https://pan.baidu.com/s/1bpBVVT9 2.设置: 点击插件-->仪表盘 添加脚本 将 ...

  6. 如何使用 lsyncd 实时同步并执行 shell 命令

    修改 lsyncd 的默认配置,不直接执行rsync 进行同步,而是改用自己的脚本. binary 指定我们的脚本 vim /usr/local/lsyncd/etc/lsyncd.conf sett ...

  7. 作为php了解一下共享内存的概念及优缺点

    共享内存是一种在相同机器中两个正在运行的进程之间共享和传递数据的有效方式,不同进程之间共享的内存通常安排为同一段物理内存:顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.一个进程可创建一 ...

  8. Linux内核Socket参数调优

    可调优的内核变量存在两种主要接口:sysctl命令和/proc文件系统,proc中与进程无关的所有信息都被移植到sysfs中.IPV4协议栈的sysctl参数主要是sysctl.net.core.sy ...

  9. 【题解】Luogu P5068 [Ynoi2015]我回来了

    众所周知lxl是个毒瘤,Ynoi道道都是神仙题,这道题极其良心,题面好评 原题传送门 我们先珂以在\(O(n^2)\)的时间内bfs求出任意两点距离 我们考虑如何计算从一个点到所有点的最短路长度小于等 ...

  10. Angular4.X 介绍

    Angular4.X 介绍 写在前面 为什么突然有想学习一点 angular 的知识呢?因为前几天突然在头条看到一个帖子,说,现在JavaScript成功的干过Java成为最火的编程语言,而JavaS ...