1 条题解
-
0
题意简述
机器人从 出发,在 矩形内移动,碰到边界时会反转对应方向的指令(所有
L/R互换,或所有U/D互换),并从那一步重新开始。脚本 连续执行 次(),求总共有多少次经过 (初始点不计)。关键观察
反射边界等价于在一个大小为 的环面上运动。具体而言,对横坐标模 ,纵坐标模 ,可以将机器人的真实位置映射到环面上的一个点。机器人每一步移动后,其在环面上的坐标都是确定的,且不依赖反射的具体发生。
因此,整个问题可以转化为:
- 执行一遍脚本 ( 步),记录每一步移动后在环面上的坐标 ,并统计每个坐标出现的次数(哈希表
cnt)。 - 设一遍脚本的净位移(在环面上)为 (即循环结束后坐标的模余数)。则第 遍( 从 到 )执行前,机器人的起始环面坐标为 。
- 在第 遍中,某一步的环面坐标等于该步的 加上起始偏移。要使其等于 ,需要满足:$$x_j + i \cdot dx \equiv 0 \pmod{2w}, \quad y_j + i \cdot dy \equiv 0 \pmod{2h} $$也就是:$$x_j \equiv -i \cdot dx \pmod{2w}, \quad y_j \equiv -i \cdot dy \pmod{2h} $$
- 所以对于每个 ,我们只需在哈希表中查找键值 $\left((-i \cdot dx \bmod 2w), (-i \cdot dy \bmod 2h)\right)$ 对应的计数,累加到答案即可。
复杂度
- 对每组数据,遍历脚本一遍 ,哈希表操作 。
- 枚举 从 到 共 次,每次 查询。由于 ,总复杂度 。
- 总时间复杂度 ,完全可行。
参考代码
#include <bits/stdc++.h> using namespace std; using ll = long long; const int N = 1e6 + 5; string s; ll n, k, w, h; ll tx[2*N], ty[2*N]; map<pair<ll, ll>, ll> cnt; int main() { cin.tie(0)->sync_with_stdio(0); int t; cin >> t; while (t--) { cin >> n >> k >> w >> h >> s; cnt.clear(); ll x = 0, y = 0; for (int i = 0; i < n; i++) { if (s[i] == 'L') x--; if (s[i] == 'R') x++; if (s[i] == 'D') y--; if (s[i] == 'U') y++; x = (x + 2*w) % (2*w); y = (y + 2*h) % (2*h); cnt[{x, y}]++; } ll ans = 0; for (int i = 0; i < k; i++) { ll vx = (-i*x%(2*w) + 2*w)%(2*w); ll vy = (-i*y%(2*h) + 2*h)%(2*h); ans += cnt[{vx, vy}]; } cout << ans << '\n'; } } - 执行一遍脚本 ( 步),记录每一步移动后在环面上的坐标 ,并统计每个坐标出现的次数(哈希表
- 1
信息
- ID
- 6912
- 时间
- 3000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者