Description

Link.

在一个数轴上给你三个点,移动方法是彼此为中点进行跳跃,不能同时越过两颗棋子。

给出初始状态和目标状态,问能否从初始状态跳到目标状态。若能,输出最少步数。

棋子之间互相没有差别。

Solution

这道题是我们去年学倍增的时候LF给我们放的一道题(实际上和倍增没有半毛钱的关系。

啊对我就是一道题从去年做到今年(我不管做出来了就是我的题量XD/xyx

不扯了说正事儿。

其实拿到这道题我是很懵的,完全不知道该怎么入手。

然后我们拿出传统手艺手玩数据。我们可以发现对于一个三元组 \((x,y,z)\) 只有三种移动的方案:

(啊对了,说一下这里的三元组表示的是一种位置关系,即 \(x\) 在左 \(y\) 在中间 \(z\) 在右)

中间往两边跳

  1. \(y\) 以 \(x\) 为中点进行跳跃,三元组变为:\((x-(y-x),x,z)\implies(2x-y,x,z)\)
  1. \(y\) 以 \(z\) 为中点进行跳跃,三元组变为:\((x,z,z+(z-y))\implies(x,z,2z-y)\)

两边往中间跳

这里方便讨论我们不妨设 \(dis_{1}\) 为 \(x\) 和 \(y\) 之间的距离,\(dis_{2}\) 为 \(y\) 和 \(z\) 之间的距离。

当 \(dis_{1} > dis_{2}\)

  1. \(x\) 以 \(y\) 为中点进行跳跃,三元组变为:\((y,y+dis_{1},z)\implies(y,2y-x,z)\)

当 \(dis_{1} < dis_{2}\)

  1. \(z\) 以 \(y\) 为中点进行跳跃,三元组变为:\((x,y-dis_{2},y)\implies(x,2y-z,y)\)

当 \(dis_{1}=dis_{2}\)

无法继续跳,也就是我们的边界。

好,现在把所有我们已知的条件串起来看:这不就是一棵二叉树吗?

对呀,这就是一棵二叉树(我在说什么

为什么这一定是一棵树呢?想一想就明白了,就像数学中的收敛一样,最后一定会出现 \(dis_{1}=dis_{2}\) 的情况。

而且这棵树是唯一确定的。

那么这道题的答案是什么就很明确了。

首先判断YES或NO的情况我们只需要判断初始状态和目标状态是否在统一棵状态树上即可。

最小的步数就是他们两个在树上的距离。

暴力肯定是不可取的。

但是我们可以通过模拟暴力的情景来得到优化的策略。

比如我们思考一个数据:\(x,y,z\)。

其中 \(y\) 是一个 远大于 \(x\) 的数。

方便起见我们令 \(z=y+1\)

暴力此时会不停的让 \(z\) 以 \(y\) 为中点跳。

此时我们回顾一下题面:

棋子之间互相没有差别。

没错,每颗棋子之间其实是没有任何差别的。

打个比方说,现在 \(z\) 以 \(y\) 为中点进行了跳跃,其本质就是 \(z\) 和 \(y\) 一起往左平移了 \(z-y\) 步。

这就意味着,我们不需要老老实实的每次都跳,我们可以直接获得 \(z\) 跳跃的次数即 \((y-x)\div(z-y)\) 次。

再推一下就是欧几里得最大公约数的形式了,也就是说我们在 \(log_{2}\) 的复杂度解决了这个问题。

最后二分一下到LCA的距离,这道题就被你暴切啦

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue> using namespace std; int a, b, c;
int x, y, z; void sort(int& x, int& y, int& z) {
vector < int > vec;
vec.push_back(x);
vec.push_back(y);
vec.push_back(z);
sort(vec.begin(), vec.end());
x = vec[0], y = vec[1], z = vec[2];
} void Initialization() {
scanf("%d %d %d", &a, &b, &c);
scanf("%d %d %d", &x, &y, &z);
sort(a, b, c);
sort(x, y, z);
} int GetRoot(int& x, int& y, int& z) {
int dis1 = y - x;
int dis2 = z - y;
if (dis1 ^ dis2) {
int temp;
if (dis1 < dis2) {
temp = dis2 / dis1;
if (!(dis2 % dis1)) --temp;
x += temp * dis1;
y += temp * dis1;
}
else {
temp = dis1 / dis2;
if (!(dis1 % dis2)) --temp;
z -= temp * dis2;
y -= temp * dis2;
}
return temp + GetRoot(x, y, z);
}
else return 0;
} void ArriveK(int& x, int& y, int& z, int key) {
int dis1 = y - x;
int dis2 = z - y;
if (dis1 < dis2) {
int temp = dis2 / dis1;
if (!(dis2 % dis1)) --temp;
if (temp >= key) {
x += key * dis1;
y += key * dis1;
}
else {
x += temp * dis1;
y += temp * dis1;
ArriveK(x, y, z, key - temp);
}
}
else {
int temp = dis1 / dis2;
if (!(dis1 % dis2)) --temp;
if (temp >= key) {
z -= key * dis2;
y -= key * dis2;
}
else {
z -= temp * dis2;
y -= temp * dis2;
ArriveK(x, y, z, key - temp);
}
}
} signed main() {
Initialization();
int a0 = a, b0 = b;
int c0 = c, x0 = x;
int y0 = y, z0 = z;
int rt1 = GetRoot(x0, y0, z0);
int rt2 = GetRoot(a0, b0, c0);
if (a0 ^ x0 || b0 ^ y0 || c0 ^ z0) return puts("NO") & 0;
if (rt1 < rt2) ArriveK(a, b, c, rt2 - rt1);
else ArriveK(x, y, z, rt1 - rt2);
int l = 0, r = min(rt1, rt2);
while (l < r) {
int mid = (l + r) >> 1;
a0 = a, b0 = b, c0 = c;
x0 = x, y0 = y, z0 = z;
ArriveK(x0, y0, z0, mid);
ArriveK(a0, b0, c0, mid);
if (x0 == a0 && y0 == b0 && z0 == c0)
r = mid;
else
l = mid + 1;
}
printf("YES\n%d\n", max(rt1, rt2) - min(rt1, rt2) + (l << 1));
return 0;
}

Solution -「洛谷 P1852」跳跳棋的更多相关文章

  1. Solution -「洛谷 P4372」Out of Sorts P

    \(\mathcal{Description}\)   OurOJ & 洛谷 P4372(几乎一致)   设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...

  2. Note/Solution -「洛谷 P5158」「模板」多项式快速插值

    \(\mathcal{Description}\)   Link.   给定 \(n\) 个点 \((x_i,y_i)\),求一个不超过 \(n-1\) 次的多项式 \(f(x)\),使得 \(f(x ...

  3. Solution -「洛谷 P4198」楼房重建

    \(\mathcal{Description}\)   Link.   给定点集 \(\{P_n\}\),\(P_i=(i,h_i)\),\(m\) 次修改,每次修改某个 \(h_i\),在每次修改后 ...

  4. Solution -「洛谷 P6577」「模板」二分图最大权完美匹配

    \(\mathcal{Description}\)   Link.   给定二分图 \(G=(V=X\cup Y,E)\),\(|X|=|Y|=n\),边 \((u,v)\in E\) 有权 \(w( ...

  5. Solution -「洛谷 P6021」洪水

    \(\mathcal{Description}\)   Link.   给定一棵 \(n\) 个点的带点权树,删除 \(u\) 点的代价是该点点权 \(a_u\).\(m\) 次操作: 修改单点点权. ...

  6. Solution -「洛谷 P4719」「模板」"动态 DP" & 动态树分治

    \(\mathcal{Description}\)   Link.   给定一棵 \(n\) 个结点的带权树,\(m\) 次单点点权修改,求出每次修改后的带权最大独立集.   \(n,m\le10^5 ...

  7. Solution -「洛谷 P5236」「模板」静态仙人掌

    \(\mathcal{Description}\)   Link.   给定一个 \(n\) 个点 \(m\) 条边的仙人掌,\(q\) 组询问两点最短路.   \(n,q\le10^4\),\(m\ ...

  8. Solution -「洛谷 P4320」道路相遇

    \(\mathcal{Description}\)   Link.   给定一个 \(n\) 个点 \(m\) 条边的连通无向图,并给出 \(q\) 个点对 \((u,v)\),询问 \(u\) 到 ...

  9. Solution -「洛谷 P5827」边双连通图计数

    \(\mathcal{Description}\)   link.   求包含 \(n\) 个点的边双连通图的个数.   \(n\le10^5\). \(\mathcal{Solution}\)    ...

  10. Solution -「洛谷 P5827」点双连通图计数

    \(\mathcal{Description}\)   link.   求有 \(n\) 个结点的点双连通图的个数,对 \(998244353\) 取模.   \(n\le10^5\). \(\mat ...

随机推荐

  1. 暑期实习开始啦「GitHub 热点速览」

    无巧不成书,刚好最近有小伙伴在找实习,而 GitHub 热榜又有收录实习信息的项目在榜.所以,无意外本周特推就收录了这个实习项目,当然还有国内版本.除了应景的实习 repo 之外,还有帮你管理文件的 ...

  2. 【Python&目标识别】labelimg报错IndexError: list index out of range

            博主在使用labelimg选取深度学习样本时,命令行报错IndexError: list index out of range,几经周折终于解决了,所以跟大家分享一下.         ...

  3. Pytorch-PyG图神经网络依赖环境安装(Anaconda)

    1.默认用户在Anaconda的虚拟环境中已安装Pytorch 2.打开anaconda prompt命令窗, activate "你的虚拟环境名称" 3.在激活后的虚拟环境下输入 ...

  4. memcached使用中踩的一些坑

    背景 线上启用memcached(以下简称mc)作为热点缓存组件已经多年,其稳定性和性能都经历住了考验,这里记录一下踩过的几个坑. 大key存储 某年某月某日,观察mysql的读库CPU占比有些异常偏 ...

  5. 一次与 ChatGPT 的 .NET 面试问答

    以常用问题来面试机器人,机器人是否能够合格 1. 您能描述一下您曾经在.NET项目中集成硬件设备的经历吗?这个过程是怎样的,您面临了哪些挑战? GPT 回答:当我在.NET项目中集成硬件设备时,我首先 ...

  6. CompletableFuture之批量上传

    前言 最近接到一个需求,批量上传图片到服务器及实时更新上传进度.当处理大量文件上传任务时,效率是一个关键因素.传统的串行方式会导致任务耗时较长,而使用并发处理可以极大地提高上传效率.想到很久之前用Co ...

  7. BitLocker加密过程中断断电,能否恢复数据?

    BitLocker是Windows系统提供的磁盘加密功能,用户自己可以手动开启.在访问受BitLocker保护的磁盘分区时,需要先提供正确的密码.秘钥或是BEK文件.如果使用BitLocker将系统盘 ...

  8. CF1580C Train Maintenance题解

    我们以 \(\sqrt m\) 为分界点来进行平衡. 设当前在进行第 \(k\) 次操作,询问 \(i\). 对于 \(x_i + y_i \leq \sqrt m\),可以在 \(last_{x_i ...

  9. P3755 [CQOI2017]老C的任务题解

    如果询问 \(x_1, y_1, x_2, y_2\), 那么询问 \((x_2, y_2)\), \((x_2, y_1 - 1)\), \((x_1 - 1, y_2)\) \((x_1 - 1, ...

  10. 【Redis】八股文(一)

    什么是Redis 基于key-value存储结构的NoSQL数据库 提供了String, Map, Set, ZSet, List等多种数据类型 功能丰富:支持发布订阅模式,能够为数据设置过期时间,能 ...