使用代码一只青蛙坐在一个网格图上,行和列都是无限的。行的计数从底部开始1, 2, ⋯,列也是这样。青蛙最初的位置是坐标(sx, sy),旅程开始了。它使用了一种特别的跳跃方法。如果它在坐标(x, y),寻找一个可以被x和y都整除的最小的z,然后向上或向右跳z步,下一步坐标可能是(x+z, y)或(x, y+z)。经过有限跳跃后(可能是0步),它停在(ex, ey)。然而,它太累了,忘记了它的起始位置。如果一个个去检查网格的所有坐标,那太笨了!请告诉青蛙一个聪明的办法,到达(ex, ey)的可能的起始位置有
时间: 2024-02-15 16:02:45 浏览: 162
这道题目可以使用数学方法来解决,具体来说,我们可以先求出从起点 (sx, sy) 开始,跳 k 次能够到达的所有坐标 (x, y),然后判断 (ex, ey) 是否在这些坐标中,如果是,则 (sx, sy) 就是一个可能的起始位置。
计算从起点 (sx, sy) 开始,跳 k 次能够到达的所有坐标 (x, y) 的方法如下:
1. 枚举所有的因子 z,计算出下一步可能到达的坐标 (x', y') = (x + z, y) 和 (x, y + z)。
2. 如果这些坐标之前没有到达过,则标记为已到达,并递归计算从 (x', y') 或 (x, y') 开始,跳 k-1 次能到达的所有坐标。
3. 如果 k=0,则返回已到达的所有坐标。
下面是使用 C++ 实现的代码:
```cpp
#include <iostream>
#include <unordered_set>
using namespace std;
unordered_set<long long> visited; // 用于记录已到达的坐标
// 递归计算从 (x, y) 开始,跳 k 次能到达的所有坐标
void dfs(long long x, long long y, int k) {
if (k == 0) {
visited.insert(x * 1000000000LL + y);
return;
}
for (long long z = 1; x + z <= 2000000000; z *= 2) {
if ((x + z) % y == 0) {
long long x1 = x + z, y1 = y;
if (visited.count(x1 * 1000000000LL + y1) == 0) {
visited.insert(x1 * 1000000000LL + y1);
dfs(x1, y1, k - 1);
}
}
if ((y + z) % x == 0) {
long long x1 = x, y1 = y + z;
if (visited.count(x1 * 1000000000LL + y1) == 0) {
visited.insert(x1 * 1000000000LL + y1);
dfs(x1, y1, k - 1);
}
}
}
}
int main() {
long long sx, sy, ex, ey;
cin >> sx >> sy >> ex >> ey;
for (int k = 0; k <= 60; k++) { // 跳 k 次最多到达 2^k 个点
visited.clear();
dfs(sx, sy, k);
if (visited.count(ex * 1000000000LL + ey) != 0) {
cout << sx << " " << sy << endl;
return 0;
}
}
cout << "No solution" << endl;
return 0;
}
```
在这个代码中,我们使用了一个哈希表 visited 来记录已经到达的坐标,其中的 key 是将 x 和 y 合并为一个 long long 类型的整数。我们使用 dfs 函数来递归计算从 (x, y) 开始,跳 k 次能到达的所有坐标,然后在主函数中枚举 k 的值,如果 (ex, ey) 在已到达的坐标中,则输出起始位置 (sx, sy),否则输出 No solution。
阅读全文