『题解』Luogu P7018 [CERC2013]Bus
题目大意
有一个公交车,初始时有 \(n\) 个人,每停一站,就会先下去一个人,然后再下去车上剩余的人数的一半。已知经过了 \(k\) 个站后,车上没人了。问:一开始车上有多少人(即 \(n\) 为多少)?
多组数据。
思路
正向开公交车,递推公式为:\(a_i=a_{i+1}-1-\dfrac{a_{i+1}}{2}\) (设 \(a_k\) 为初始站,\(a_1\) 为有 \(n\) 个人时的站台),那么倒着开(时光倒流)的公式也很容易得出:\(a_i=a_{i-1} \times 2+1\) (同上)。由于经过了 \(k\) 个站,每次都会正向推 \(k\) 次,变成 \(0\)。所以我们从 \(0\) 开始逆推,推 \(k\) 次,即可得到答案。
但是又有多组数据,我更想尽可能地节省时间,于是我预处理出了所有答案。直接套上面的逆推公式即可。这样的话,查询可以 \(\mathcal{O}(1)\) 时间复杂度。
代码
#include <iostream>
using namespace std;
int t,k,ans[35];
int main(){
cin >> t;
for(int i=1; i<=30; i++){
ans[i]=ans[i-1]*2+1;
// 预处理,算出经过1~30个站后人数位 0 时,最初有多少人。
// 查询时可 O(1)。
}
while(t--){
cin >> k;
cout << ans[k] << endl;
}
return 0;
}