『题解』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;
}
posted @ 2022-01-21 21:23  仙山有茗  阅读(52)  评论(0编辑  收藏  举报