AT2202 硬度フェスティバル / Kode Festival 题解

Content

\(2^n\) 块石头,第 \(i\) 块石头硬度为 \(a_i\)。重复执行以下操作直到只剩下一块石头为止:

  • 让当前编号为 \((1,2)\)\((3,4)\)、…… 的石头互相碰撞,若一对中有一个石头比另一个石头硬度大,则硬度小的石头消失,硬度大的石头的硬度减去原来硬度小的石头的硬度。若一对中的两个石头硬度都相等,则随机选择一块消失,另一块硬度不变。
  • 将剩下的石头按照它们的初始顺序重现排列并编号。

求最后剩下的一块石头的硬度。

数据范围:\(1\leqslant n\leqslant 18\)\(1\leqslant a_i\leqslant 10^9\)

Solution

讲一下不用队列的方法,对新手来说会较为友好。

我们开一个 \(\textit{vis}\) 数组用来存储当前石头是否已经消失。然后直接重复模拟的过程,每次找一对当前相邻的石头进行碰撞。可以发现若两个石头的硬度都相等,随机选择一块消失并不会导致后面的结果不同,因此我们随便定一个石头消失就好了。

一轮结束后再循环判断当前是否只有一个石头,如果是的话直接输出这块石头的硬度即可。

Code

int a[1 << 19], vis[1 << 19]; // << 为左移符号,<< x 相当于乘 2^x

int main() {
    int n = 1 << Rint, deb1 = -1, deb2 = -1, ans = -1;
    F(int, i, 1, n) a[i] = Rint, vis[i] = 1;
    while(1) {
        F(int, i, 1, n) if(vis[i] == 1) {
            if(deb1 == -1) deb1 = i;
            else {
                deb2 = i;
                if(a[deb1] > a[deb2]) a[deb1] = a[deb1] - a[deb2], vis[deb2] = 0, deb1 = deb2 = -1;
                else a[deb2] = a[deb2] - a[deb1], vis[deb1] = 0, deb1 = deb2 = -1; 
            }
        }
        int fl = 0;
        F(int, i, 1, n) {
            fl += vis[i];
            if(vis[i]) ans = a[i];
        }
        if(fl == 1) break;
    }
    return println(ans), 0;
}
posted @ 2021-12-15 21:45  Eason_AC  阅读(19)  评论(0)    收藏  举报