传送门

神题一道。

考虑题目性质。首先对于一个状态,只存在四种情况,即最左/右边的点跳到中间,中间的点跳到左/右。而对于一个状态,显然第一种情况的两种分支不能同时存在,那么题目就可以理解为从$(a,b,c)$找到一条最短的路径可以使得其到达$(x,y,z)$,你完全可以把所有状态存下来随便跑个最短路算法,但是显然是无法承受的,而再研究题目可以发现如果根据一个状态的情况连边,所形成的图是一棵树,而且还是个二叉树,那么就可以利用这个性质。那么假设现在一个状态是$(x,y,z)$,设$t1=y-x,t2=z-y$。如果$t1==t2$,那么就代表这个节点是个根节点。为了简化题目,不考虑每个节点的儿子情况,只考虑他的父亲,那么这个题目就可以看作在一棵树里找两个点的LCA。那么如何求一个节点的第$k$个祖先?

根据gcd的一些奇奇怪怪的性质,可以发现如果$t1>t2$,那么不断将最左边的点移到中间,最多可以移$\frac{t1-1}{t2}$,根据这个也很容易算出移动后的状态。

剩下的就很好搞了, 倍增二分什么的都可以,我用的是二分。

//BZOJ 2144
//by Cydiater
//2016.10.20
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <ctime>
#include <cmath>
#include <iomanip>
#include <cstdlib>
using namespace std;
#define ll long long
#define up(i,j,n)		for(int i=j;i<=n;i++)
#define down(i,j,n)		for(int i=j;i>=n;i--)
const int MAXN=1e6+5;
const int oo=0x3f3f3f3f;
inline int read(){
	char ch=getchar();int x=0,f=1;
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int dep1,dep2,ans=0;
struct Node{
	int x,y,z;
	void Sort(){if(x>y)swap(x,y);if(x>z)swap(x,z);if(y>z)swap(y,z);}
}a,b;
bool operator == (Node x,Node y){return x.x==y.x&&x.y==y.y&&x.z==y.z;}
namespace solution{
	void init(){
		a.x=read();a.y=read();a.z=read();
		b.x=read();b.y=read();b.z=read();
	}
	int get(Node node){
		int x=node.x,y=node.y,z=node.z;
		int t1=abs(y-x),t2=abs(z-y),Ans=0;
		while(t1!=t2&&t1*t2!=0){
			if(t1<t2)swap(t1,t2);
			Ans+=(t1-1)/t2;
			int tmp=t1;t1=t2;t2=tmp%t2;
		}
		return Ans;
	}
	Node jump(Node t,int dist){
		if(get(t)<dist)return (Node){oo,oo,oo};
		t.Sort();
		while(dist){
			if(t.y-t.x>t.z-t.y){
				int t1=t.y-t.x,t2=t.z-t.y;
				if((t1-1)/t2<dist){
					dist-=(t1-1)/t2;
					t.y-=(t1-1)/t2*t2;
					t.z-=(t1-1)/t2*t2;
				}else{
					t.y-=dist*t2;
					t.z-=dist*t2;
					dist=0;
				}
			}else{
				int t1=t.y-t.x,t2=t.z-t.y;
				if((t2-1)/t1<dist){
					dist-=(t2-1)/t1;
					t.x+=(t2-1)/t1*t1;
					t.y+=(t2-1)/t1*t1;
				}else{
					t.x+=dist*t1;
					t.y+=dist*t1;
					dist=0;
				}
			}
		}
		return t;
	}
	void slove(){
		if(a==b){puts("YES");puts("0");return;}
		a.Sort();b.Sort();
		dep1=get(a);dep2=get(b);
		if(dep1<dep2){swap(a,b);swap(dep1,dep2);}
		ans+=dep1-dep2;
		a=jump(a,dep1-dep2);
		if(a.x==oo){puts("NO");return;}
		if(a==b){puts("YES");cout<<ans<<endl;return;}
		int leftt=1,rightt=1000000000,mid;
		while(leftt+1<rightt){
			mid=(leftt+rightt)>>1;
			if(jump(a,mid)==jump(b,mid))rightt=mid;
			else                        leftt=mid;
		}
		if(jump(a,leftt)==jump(b,leftt)&&jump(a,leftt).x!=oo){
			puts("YES");
			printf("%d\n",ans+(leftt<<1));
		}
		else if(jump(a,rightt)==jump(b,rightt)&&jump(a,rightt).x!=oo){
			puts("YES");
			printf("%d\n",ans+(rightt<<1));
		}
		else puts("NO");
	}
}
int main(){
	//freopen("input.in","r",stdin);
	using namespace solution;
	init();
	slove();
	return 0;
}

BZOJ2144: 跳跳棋的更多相关文章

  1. bzoj2144 跳跳棋 二分

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

  2. BZOJ2144跳跳棋——LCA+二分

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

  3. bzoj2144: 跳跳棋(二分/倍增)

    思维好题! 可以发现如果中间的点要跳到两边有两种情况,两边的点要跳到中间最多只有一种情况. 我们用一个节点表示一种状态,那么两边跳到中间的状态就是当前点的父亲,中间的点跳到两边的状态就是这个点的两个儿 ...

  4. BZOJ2144 跳跳棋[建模+LCA]

    思维题,思路比较神仙. 个人思路过程:个人只想到了只要中间棋子开始向外跳了,以后就不应该向内跳了,这样很蠢.所以应该要么先向内跳一会,要么直接开始中间的向外跳.不知道怎么处理,就卡住了. 20pts: ...

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

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

  6. 【bzoj2144】跳跳棋

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

  7. [BZOJ2144]国家集训队 跳跳棋

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

  8. [BZOJ2144][国家集训队2011]跳跳棋

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

  9. 【LCA】bzoj 2144:跳跳棋

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

随机推荐

  1. Could not obtain information about Windows NT group/user 'xxxx\xxxx', error code 0x5

    案例描述 昨晚踢球回来,接到电话说一个系统的几个比较重要作业出错,导致系统数据有些问题.让我赶紧检查看看.检查作业日志时发现,作业报如下错误(关键信息用xxx替换) The job failed.  ...

  2. .NET应用架构设计—面向查询的领域驱动设计实践(调整传统三层架构,外加维护型的业务开关)

    阅读目录: 1.背景介绍 2.在业务层中加入核心领域模型(引入DomainModel,让逻辑.数据有家可归,变成一个完整的业务对象) 3.统一协调层Application Layer(加入协调层来转换 ...

  3. BOOST.Asio——Tutorial

    =================================版权声明================================= 版权声明:原创文章 谢绝转载  啥说的,鄙视那些无视版权随 ...

  4. 问题解决——MFC error RC2170: bitmap file res\XXXXXXX.png is not in 3.00 format

    =================================版权声明================================= 版权声明:原创文章 谢绝转载  请通过右侧公告中的“联系邮 ...

  5. Mac OS X常用操作入门指南

    前两天入手一个Macbook air,在装软件过程中摸索了一些基本操作,现就常用操作进行总结, 1关于触控板: 按下(不区分左右)            =鼠标左键 control+按下        ...

  6. dom4j读取某个元素的某个属性

    一.dom4j介绍 dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的.dom4j是一个非常非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的特点, ...

  7. [python]获取当前年月

    import time time.strftime('%Y%m',time.localtime(time.time()))#获取当前年月

  8. matlab里的svmtrain的输出model里,各参数的含义

    Parameters: [5x1 double]  %结构体变量,依次保存的是 -s -t -d -g -r等参数      nr_class: 4    %分类的个数          totalS ...

  9. size_t和size_type

    size_t和size_type是为了独立于及其而定义的类型,因为比如在一台电脑上int为2b,而另一台电脑上是4b,这样就给程序的可移植性带来了麻烦.为了解决这个问题,在库内定义了如上类型,其实si ...

  10. OpenCV 之 编译和配置

    “工欲善其事,必先利其器”,下面介绍在 Win7 32位系统下,用 cmake 编译 OpenCV 的过程. 1  开发环境 1.1  Win7 Windows 7 家庭普通版,Service Pac ...