ABC319E 题解

题意

在两个房子中间,有 \(N\) 个公交站,按照如下方式移动:

  • 从起点到第 \(1\) 个公交站,用时 \(X\) 秒。
  • 从第 \(i\) 个公交站到第 \(i+1\) 个公交站,用时 \(T_i\) 秒。(时间每到 \(P_i\) 的倍数,发车一次)
  • 从第 \(N\) 个公交站到终点,用时 \(Y\) 秒。

询问 \(Q\) 次,每次给定出发时间 \(q_i\),求到达时间的最小值。

数据范围

  • \(2\le N\le 10^5\)
  • \(1\le X,Y,T_i\le 10^9\)
  • \(1\le P_i \le 8\)重点
  • \(1\le Q \le 2\times10^5\)
  • \(0\le q_i\le 10^9\)

分析

首先我们发现这个最小值是假的,直接上最近的车就好。

那么就有了一个 \(O(NQP)\) 的暴力,直接模拟。

考虑优化这个暴力。

发现 \(P_i\) 的范围很小,感受上答案的种类不会太多(可能有周期性)。

我们考虑“路上时间”的组成:车上时间 \(+\) 等车时间。

车上时间是相同的,出发时间只会影响等车时间,这个时间与当前时间 \(\bmod P_i\) 的值有关。

众所周知,\(x \equiv x-p \pmod p\)

可以推出,\(x \equiv x-\operatorname{lcm}(p,q) \pmod p\),\(x \equiv x-\operatorname{lcm}(p,q) \pmod q\)

所以对于每个时间点,它的“等车时间”与它 \(\bmod \operatorname{lcm}(1,2,3,4,5,6,7,8)\) 的“等车时间”相同。

预处理出发时间在 \(1\) ~ \(840\) 的“路上时间”,询问直接查询余数即可。

\(M=840\)

复杂度 \(O(MNP+Q)\),AT 神机能过。

code

#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define rep0(i,n) for(int i=0;i<n;i++)
#define LL long long

const int N=1e5+5;
const int M=850;
const int mod=840;
LL x,y;
LL p[N],t[N];
LL ans[M];

int Q,n;
int main(){
	cin>>n>>x>>y;
	rep(i,n-1) cin>>p[i]>>t[i];

	rep0(i,mod){//模拟
		LL nt=i+x;
		rep(j,n-1){
			while(nt%p[j]!=0) nt++;
			nt+=t[j];
		}
		nt+=y;
		ans[i]=nt;
	}

	cin>>Q;
	rep(q,Q){
		int st;cin>>st;
		cout<<ans[st%mod]+st-st%mod<<endl;
	}
	return 0;
}
posted @ 2024-03-01 22:25  Cindy_Li  阅读(30)  评论(0)    收藏  举报