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;
}

浙公网安备 33010602011771号