洛谷链接:
Aroma's Search - 洛谷https://www.luogu.com.cn/problem/CF1292B
思路:
考虑到左下的点比较密集,右上的较稀疏,所以想到枚举第一个到达的点,从这个点开始先向左下遍历,遍历完了再往右上走。我没有严格证明出来,证明部分可以看洛谷题解。大概意思是,从第 i 个点开始走到第0个点的距离比走到第i+1个点的距离短,所以开始时往左下走是最优解。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define LIMIT (ll)1e16<<2 // 最远的点的横或纵坐标(这里不能定太大也不能太小,1e16和1e17都不行)
ll x00, y00, ax, ay, bx, by; //第0个点,倍率系数
ll xs, ys, t; //初始位置,可用时间
ll cnt = 0; //可能去到的点的数量
// 下面是记录x,y坐标的数组,2^100大于1e30,而题目说了x和y最多到1e16,所以是足够的
ll x[101], y[101];
ll dist(ll a, ll b){ //计算a到b的消耗时间
return abs(x[a]-x[b]) + abs(y[a]-y[b]);
}
ll solve(ll to){ //计算先去to点最大的去到点的数量
ll res = 0; //去到点的数量
ll Time = t; //时间
ll cur = 0; //当前位置(一开始在起点)
for(ll i=to; i>0; i--){ //先向前走,知道走到第0个点
if(Time < dist(cur, i)) break; //去不到这个点了,结束
Time -= dist(cur, i);
res++;
cur = i;
}
for(ll i=to+1; i<=cnt; i++){ //回头,从to+1开始往后遍历
if(Time < dist(cur, i)) break;
Time -= dist(cur, i);
res++;
cur = i;
}
return res;
}
int main(){
ios::sync_with_stdio(false);
cin >> x00 >> y00 >> ax >> ay >> bx >> by >> xs >> ys >> t;
x[0] = xs, y[0] = ys; //0下标记录起点,其他下标记录第0~n个点
for(ll i=x00, j=y00; i<=LIMIT && j<=LIMIT; i=ax*i+bx, j=ay*j+by){
//记录除了起点外的所有可能去到的点
x[++cnt] = i; y[cnt] = j;
}
ll ans = 0;
for(ll i=1; i<=cnt; i++){ //枚举第一个去的点
ans = max(ans, solve(i));
}
cout << ans << '\n';
return 0;
}