📜  门| GATE-CS-2000 |第 41 题(1)

📅  最后修改于: 2023-12-03 14:58:24.287000             🧑  作者: Mango

门| GATE-CS-2000 |第 41 题

题目描述

有 $2$ 个人,$A$ 和 $B$,在一个有 $n$ 个门的走廊上玩游戏。最初所有门都是关闭的。$A$ 开始,他经过每扇门都打开它,然后每第二扇门再次关闭。接下来,$B$ 经过每第三扇门,如果该门开着,则关闭它;如果该门关闭,则打开它。继续这个过程,依次找到第 $k$ 个人,重复这个操作。问最后门的状态是打开的还是关闭的?

输入格式

第一个参数为 $n$,表示有 $n$ 个门 $( 1 \leq n \leq 10^6)$。

第二个参数为 $k$,表示有 $k$ 个人 $( 1 \leq k \leq 10^3)$。

输出格式

如果最后门的状态是打开的,则输出 open,否则输出 closed

示例

输入:

10 2

输出:

closed
解题思路

通过观察题目,可以得出以下结论:

  1. 如果一个门被经过了偶数次,则门的状态会是关闭的。

  2. 如果一个门被经过了奇数次,则门的状态会是打开的。

  3. 如果经过 i 个门,则第 i 个门一定会被打开。

通过上述结论可以得出,每个人经过经过的门的状态只与门的编号有关,可以用一个 bool 数组 doors 维护门的状态。

我们可以按照题意模拟这个过程,对于每个人对应的门进行状态处理,最终统计打开的门的数量,判断门的状态是否是打开的。

设门的数量为 $n$,人的数量为 $k$,时间复杂度为 $\mathcal{O}(nk)$。

复杂度分析

时间复杂度为 $\mathcal{O}(nk)$。

空间复杂度为 $\mathcal{O}(n)$,即 bool 数组 doors 的空间。

参考代码
bool doors[maxn];

void play(int n) {
    for (int i = 1; i <= n; i++) {
        for (int j = i; j <= n; j += i) {
            doors[j] ^= 1;
        }
    }
}

int main() {
    int n, k;
    cin >> n >> k;

    play(k);

    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        if (doors[i]) cnt++;
    }

    if (cnt % 2 == 0) {
        cout << "closed" << endl;
    } else {
        cout << "open" << endl;
    }

    return 0;
}

注:为了避免函数传递数组时需要传递数组长度的问题,此代码直接将数组大小定义为常量 maxn,且数组下标从 $1$ 开始。