BZOJ #2144 跳跳棋 (lca和gcd的模型转化和完美结合)
题目描述:
在数轴上有三个棋子,初始时位置为x,y,z,要求用最少的操作步数让位置变成a,b,c。每次操作可以任选一颗棋子,以另一个棋子为中轴跳动,跳动后距离不边,且每次只能跳过一颗棋子。
解题思路:
因为有限制,两边只有一颗棋子能跨过中间跳,而中间的棋子就可以往两边跳。如果注意观察的话,会发现往两边跳和往中间跳是互逆的。所以我们把状态连接起来是一棵树,而题目要求的就是始末状态在树上的距离。但如果每次暴力往上跳的话,时间复杂度会爆炸。再仔细观察的话,还会发现设中间棋子与两边棋子的距离为(l,r)的话,假设l>r,那么每次往上跳就会变成(l−r,r),而这与求gcd的过程类似,所以我们就可以log地求出一个点的祖先。外面二分深度,就能求出lca。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int inf = 1e9; 7 int x, y, z, len1, len2, len; 8 9 struct sta { 10 int x, y, z; 11 sta(int _x = 0, int _y = 0, int _z = 0) {x = _x, y = _y, z = _z;} 12 void sort() { 13 if (y < x) swap(x, y); 14 if (z < x) swap(x, z); 15 if (z < y) swap(z, y); 16 } 17 } st, en, s, e; 18 19 int equal(sta a, sta b) { 20 if (a.x != b.x || a.y != b.y || a.z != b.z) return 0; 21 return 1; 22 } 23 24 sta find(sta now, int r, int &len) { 25 int k = 0; 26 for (len = 0; r; len += k) { 27 int a = now.y - now.x, b = now.z - now.y; 28 if (a == b) return now; 29 if (a > b) { 30 k = min((a - 1) / b, r); 31 r -= k; 32 now.y -= k * b, now.z -= k * b; 33 } 34 if (a < b) { 35 k = min((b - 1) / a, r); 36 r -= k; 37 now.x += k * a, now.y += k * a; 38 } 39 } 40 return now; 41 } 42 43 void divide() { 44 st = find(st, len1 - len2, len); 45 int l = 0, r = len2; 46 while (l < r) { 47 int m = l + r >> 1; 48 if (equal(find(st, m, len), find(en, m, len))) r = m; else l = m + 1; 49 } 50 printf("%d", l * 2 + len1 - len2); 51 } 52 53 int main() { 54 scanf("%d %d %d", &x, &y, &z); 55 st = sta(x, y, z), st.sort(); 56 scanf("%d %d %d", &x, &y, &z); 57 en = sta(x, y, z), en.sort(); 58 s = find(st, inf, len1); 59 e = find(en, inf, len2); 60 if (!equal(s, e)) { 61 printf("NO\n"); 62 return 0; 63 } 64 printf("YES\n"); 65 if (len1 < len2) swap(st, en), swap(len1, len2); 66 divide(); 67 return 0; 68 }
标签:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术