题目描述

跳跳棋是在一条数轴上进行的。棋子只能摆在整点上。每个点不能摆超过一个棋子。

我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置。我们要通过最少的跳动把他们的位置移动成x,y,z。(棋子是没有区别的)

跳动的规则很简单,任意选一颗棋子,对一颗中轴棋子跳动。跳动后两颗棋子距离不变。一次只允许跳过1颗棋子。

写一个程序,首先判断是否可以完成任务。如果可以,输出最少需要的跳动次数。

输入输出格式

输入格式:

第一行包含三个整数,表示当前棋子的位置a b c。(互不相同)

第二行包含三个整数,表示目标位置x y z。(互不相同)

输出格式:

如果无解,输出一行NO。

如果可以到达,第一行输出YES,第二行输出最少步数。

输入输出样例

输入样例#1:

1 2 3
0 3 5
输出样例#1:

YES
2

说明

20% 输入整数的绝对值均不超过10

40% 输入整数的绝对值均不超过10000

100% 绝对值不超过10^9

非常有趣的一道题目。

可以发现只有唯一的一种方案向里跳,并且一直这样跳最后总会达到一种再也不能向里跳的状态。

于是我们就可以把向里跳看成在树上向父亲走,而最后b-a = c-b 的状态就是根节点。

首先如果两个状态的树根不一样,无解;否则就是一个求LCA的问题了,直接倍增即可。

/*
向前跳: a[1] -= a[2] (须满足 a[1] > a[2])
向后跳: a[2] -= a[1] , a[0] += a[1] (须满足 a[1] < a[2])
a[1] == a[2] 就不能跳了
*/
#include<bits/stdc++.h>
#define ll long long
using namespace std; struct node{
int x,y,z;
bool operator !=(const node &u)const{
return x!=u.x||y!=u.y||z!=u.z;
}
}A,B; int a[3],b[3];
unsigned int ans; node getroot(node x){
if(x.y==x.z) return x; if(x.y>x.z) return getroot((node){x.x,(x.y-1)%x.z+1,x.z}); else{
int o=(x.z-1)/x.y;
x.x+=o*x.y,x.z-=o*x.y;
return getroot(x);
}
} int getdeep(node x){
if(x.y==x.z) return 0; if(x.y>x.z){
int o=(x.y-1)/x.z;
x.y-=o*x.z;
return getdeep(x)+o;
} else{
int o=(x.z-1)/x.y;
x.x+=o*x.y,x.z-=o*x.y;
return getdeep(x)+o;
}
} node getnode(node x,int lef){
if(x.y==x.z) return x; if(x.y>x.z){
int o=(x.y-1)/x.z; if(o>=lef) return (node){x.x,x.y-lef*x.z,x.z}; x.y-=o*x.z;
return getnode(x,lef-o);
} else{
int o=(x.z-1)/x.y; if(o>=lef) return (node){x.x+lef*x.y,x.y,x.z-lef*x.y}; x.x+=o*x.y,x.z-=o*x.y;
return getnode(x,lef-o);
}
} inline void solve(){
int da=getdeep(A),db=getdeep(B);
if(da<db) swap(da,db),swap(A,B);
if(da>db) A=getnode(A,da-db); ans=da-db; if(!(A!=B)) return; for(int i=log(db)/log(2)+1;i>=0;i--) if((1<<i)<=db){
node AA=getnode(A,1<<i);
node BB=getnode(B,1<<i);
if(AA!=BB) A=AA,B=BB,ans+=1<<(i+1);
} ans+=2;
} int main(){
for(int i=0;i<3;i++) scanf("%d",a+i);
for(int i=0;i<3;i++) scanf("%d",b+i);
sort(a,a+3),sort(b,b+3); for(int i=2;i;i--) a[i]-=a[i-1],b[i]-=b[i-1]; A=(node){a[0],a[1],a[2]},B=(node){b[0],b[1],b[2]};
if(getroot(A)!=getroot(B)){ puts("NO"); return 0;} solve(); puts("YES");
printf("%u\n",ans); return 0;
}

  

洛谷 P1852 [国家集训队] 跳跳棋的更多相关文章

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

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

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

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

  3. luogu P1852 [国家集训队]跳跳棋

    luogu 直接操作是不可能的,考虑发现一些性质.可以发现如果每次跳的棋子都是两边的,那么最多只有一种方案,那么就把这样操作得到的状态记为当前状态的父亲,从一个状态这样做一定会结束.那么如果两个状态只 ...

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

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

  5. 模板—点分治A(容斥)(洛谷P2634 [国家集训队]聪聪可可)

    洛谷P2634 [国家集训队]聪聪可可 静态点分治 一开始还以为要把分治树建出来……• 树的结构不发生改变,点权边权都不变,那么我们利用刚刚的思路,有两种具体的分治方法.• A:朴素做法,直接找重心, ...

  6. [洛谷P1527] [国家集训队]矩阵乘法

    洛谷题目链接:[国家集训队]矩阵乘法 题目背景 原 <补丁VS错误>请前往P2761 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入 ...

  7. 洛谷P1501 [国家集训队]Tree II(LCT,Splay)

    洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ...

  8. 洛谷P2619 [国家集训队2]Tree I(带权二分,Kruscal,归并排序)

    洛谷题目传送门 给一个比较有逼格的名词--WQS二分/带权二分/DP凸优化(当然这题不是DP). 用来解决一种特定类型的问题: 有\(n\)个物品,选择每一个都会有相应的权值,需要求出强制选\(nee ...

  9. 洛谷 P1407 [国家集训队]稳定婚姻 解题报告

    P1407 [国家集训队]稳定婚姻 题目描述 我国的离婚率连续7年上升,今年的头两季,平均每天有近5000对夫妇离婚,大城市的离婚率上升最快,有研究婚姻问题的专家认为,是与简化离婚手续有关. 25岁的 ...

随机推荐

  1. BZOJ day2

    十六题...(好难啊) 1051105910881191119214321876195119682242243824562463276128184720

  2. 【COGS 14】 [网络流24题] 搭配飞行员 网络流板子题

    用网络流水二分图的模型(存一下板子) #include <cstdio> #include <cstring> #include <algorithm> #defi ...

  3. Spring学习--使用 utility scheme 定义集合及 p命名空间

    util schema 定义集合: 使用基本的集合标签定义集合时 , 不能将集合作为独立的 Bean 定义 , 导致其他 Bean 无法引用该集合 , 所以无法在不同 Bean 之间共享集合. 可以用 ...

  4. Spring 中 AbstractExcelView 支持根据模板生成Excel文件. 通过设置 view 的 URL 属性指定模板的路径

     注意:1. 模板需放在 WEB-INF 目录下2. 指定模板路径时不需要添加扩展名, Spring将自动添加 .xls 到URL 属性中.3. 在指定URL前需先设置 view 的 Applicat ...

  5. 【Foreign】哈密顿回路 [MIM]

    哈密顿回路 Time Limit: 15 Sec  Memory Limit: 256 MB Description Input Output Sample Input 4 10 0 3 2 1 3 ...

  6. DotNETCore 学习笔记 日志

    Logging --------------------------------------------------------------------------------------- Impl ...

  7. android ARM 汇编学习 —— hello world

    android ARM 汇编学习—— 在 android 设备上编译c/cpp代码并用objdump/readelf等工具分析 adb putty 连上手机,用busybox vi 写一个 hello ...

  8. chromium源代码下载(Win7x64+VS2013sp2, 39.0.2132.2)

    chromium源代码下载(Win7x64+VS2013sp2, 39.0.2132.2) http://www.aichengxu.com/diannao/1000251.htm 前后折腾了四天,当 ...

  9. mvn常用的构建命令

    mvn -v 查看maven版本 mvn compile 编译 mvn test 测试 mvn package 打包 mvn clean 删除target mvn install 安装jar包到本地仓 ...

  10. Linux编写Shell脚本

    ——<Linux就该这么学>笔记Shell脚本命令的工作方式有两种 交互式: 用户每输入一条命令就立即执行 批处理: 由用户事先编写好一个完整的Shell脚本,Shell会一次性执行脚本中 ...