CF1292B(思维)
Aroma's Search
题目描述
这个空间可以看作是一个二维平面,在其内部有着无限多的数据点,从 \(0\) 开始标号,它们的坐标定义如下:
- 第 \(0\) 个点的坐标为 \((x_0, y_0)\)。
- 对于 \(i > 0\),第 \(i\) 个点的坐标为 \((x_i, y_i) = (a_x \cdot x_{i-1} + b_x, a_y \cdot y_{i-1} + b_y)\)。
初始时 Aroma 的位置为 \((x_s, y_s)\)。她只能留在 OS 空间中最多 \(t\) 秒,她不需要返回初始位置 \((x_s, y_s)\) 也能传送回家。
在 OS 空间中,Aroma 可以做如下操作:
- 在点 \((x, y)\) 上时,Aroma 可以移动到这四个点之一:\((x-1, y), (x+1, y), (x, y-1), (x, y+1)\)。这个操作需要耗费 \(1\) 秒。
- 如果 Aroma 当前的位置上有数据点,她可以收集它。我们可以假定这个操作耗费 \(0\) 秒。当然,每个数据点只能被收集一次。
计算在 \(t\) 秒内最多能收集的数据点的个数吗?
思路:
对于点集 \(\{(x_i, y_j) \mathrel{|} x_i = x_{i - 1}×a_x + b_x, y_i = y_{i - 1}×a_y + b_y\}\)我们可以写出这些点\(x, y\)坐标的通项公式: \(x_n = x_0 × a_x ^ n + b_x × \left(a_x ^ {n - 1} + a_x ^ {n - 2} + \dots + a_x ^ 2 + a_x ^ 1 + a_x ^ 0\right)\), 可以发现\(b_x\)乘的那一部分是一个等比数列,那么最终的通项公式就是\(x_n = x ^ 0×a_x ^ n + \frac{a_x ^ n - 1}{a_x - 1}\). 因为\(a_x ^ n\)是一个指数函数,当\(n\)增大的时候,点在二维平面上就会越来越稀疏,所以想要尽可能的收集多的数据点,就应该先向\(P_0\)方向收集再向\(p_0 \rightarrow P_n\)方向收集, 但是起始点应该先向哪个点移动并不知道,所以需要枚举第一个走向的点,然后按照\(P_i \rightarrow P_0 \rightarrow P_n\)这个原则走。
int n = 0;
i64 a, b, c, d, sx, sy, t;
std::cin >> x[0] >> y[0] >> a >> c >> b >> d >> sx >> sy >> t;
auto dis = [&](i64 x1, i64 y1, i64 x2, i64 y2) -> i64 {
return std::llabs(x1 - x2) + std::llabs(y1 - y2);
};
while(++n) {
x[n] = x[n - 1] * a + b;
y[n] = y[n - 1] * c + d;
if (x[n] > sx && y[n] > sy && dis(sx, sy, x[n], y[n]) > t) break;
}
int ans = 0;
for (int i = 0; i <= n; i++) {
int res = 0;
i64 now = t;
if (now >= dis(x[i], y[i], sx, sy)) res++, now -= dis(x[i], y[i], sx, sy);
else continue;
for (int j = i - 1; j >= 0; j--) {
if (now >= dis(x[j], y[j], x[j + 1], y[j + 1])) res++, now -= dis(x[j], y[j], x[j + 1], y[j + 1]);
else {
ans = std::max(ans, res);
pos = i;
break;
}
}
for (int j = 1; j <= n; j++) {
if (now >= dis(x[j], y[j], x[j - 1], y[j - 1])) res += j > i, now -= dis(x[j], y[j], x[j - 1], y[j - 1]);
else {ans = std::max(ans, res); break;}
}
}
std::cout << ans << "\n";

浙公网安备 33010602011771号