CF1292B Aroma's Search 题解

Content

给定一个坐标系,已知第一个点的坐标为 \((x_0,y_0)\),第 \(i(i>0)\) 个点的坐标满足这样的两个递推式:\(x_i=a_xx_{i-1}+b_x,y_i=a_yy_{i-1}+b_y\)。现在从 \((x_s,y_s)\) 出发,每秒钟能够上下左右走一个格子,求在 \(t\) 秒内最多能够经过的点的个数。

数据范围:\(1\leqslant x_0,y_0,x_s,y_s,t\leqslant 10^{16},2\leqslant a_x,a_y\leqslant 100,0\leqslant b_x,b_y\leqslant 10^{16}\)

Solution

我们发现,坐标的增长是指数级的。因此坐标在 \(10^{16}\) 以内的点其实并不多,甚至可以说是非常有限。而且可以确定的是,要想经过点最多,一定得要从近的点走到远的点。所以我们考虑直接暴力模拟,先往左跑,再往右跑,看哪边能够经过的点多就取哪一边的答案。

依据这种思路写的代码跑的挺快,最慢的点大约也就 \(30\) ms,不用担心会超时。

Code

long long ax, ay, bx, by, xs, ys, t, x[100007], y[100007];

int main() {
	getll(x[0]), getll(y[0]), getll(ax), getll(ay), getll(bx), getll(by), getll(xs), getll(ys), getll(t);
	int num = 0;
	while(x[num] <= xs + t && y[num] <= ys + t) num++, x[num] = ax * x[num - 1] + bx, y[num] = ay * y[num - 1] + by;
	ll tmp = 0; int ans = 0;
	_for(i, 0, num) {
		tmp = t - llabs(x[i] - xs) - llabs(y[i] - ys);
		int j = i + 1, cnt = 0;
		while(tmp >= 0 && j <= num) cnt++, tmp -= (x[j] - x[j - 1] + y[j] - y[j - 1]), j++;
		cnt += (tmp >= 0), ans = max(ans, cnt), tmp = t - abs(x[i] - xs) - abs(y[i] - ys), j = i - 1, cnt = 0;
		while(tmp >= 0 && j <= num) cnt++, tmp -= (x[j + 1] - x[j] + y[j + 1] - y[j]), j--;
		cnt += (tmp >= 0), ans = max(ans, cnt);
	}
	writeint(ans);
	return 0;
}
posted @ 2021-12-16 15:11  Eason_AC  阅读(35)  评论(0)    收藏  举报