AcWing第23场周赛题解

A. 4003. 完全平方数

题目链接:https://www.acwing.com/problem/content/4006/

题目大意:求 \(n\) 个数中最大的非完全平方数。

解题思路:循环一遍即可。

示例程序:

#include <bits/stdc++.h>
using namespace std;

bool check(int a) {
    if (a < 0) return false;
    int b = sqrt(a);
    return b * b == a;
}

int n, a, mx = -1e7;

int main() {
    cin >> n;
    while (n--) {
        cin >> a;
        if (!check(a))
            mx = max(mx, a);
    }
    cout << mx << endl;
    return 0;
}

B. 4004. 传送阵

题目链接:https://www.acwing.com/problem/content/4007/

题目大意:略。

解题思路:搜索(判连通性)+枚举(求最小成本)。

示例程序:

#include <bits/stdc++.h>
using namespace std;

int n, r1, c1, r2, c2;
char s[55][55];
int dir[4][2] = {-1, 0, 1, 0, 0, -1, 0, 1};
int cc[55][55];

bool in_map(int x, int y) {
    return x >= 0 && x < n && y >= 0 && y < n;
}

void dfs(int x, int y, int c) {
    cc[x][y] = c;
    for (int i = 0; i < 4; i++) {
        int xx = x + dir[i][0], yy = y + dir[i][1];
        if (in_map(xx, yy) && s[xx][yy] == '0' && !cc[xx][yy])
            dfs(xx, yy, c);
    }
}

int main() {
    cin >> n >> r1 >> c1 >> r2 >> c2;
    r1--, c1--, r2--, c2--;
    for (int i = 0; i < n; i++)
        cin >> s[i];
    dfs(r1, c1, 1);
    if (cc[r2][c2]) {
        cout << 0 << endl;
        return 0;
    }
    dfs(r2, c2, 2);
    int ans = (r1-r2)*(r1-r2) + (c1-c2)*(c1-c2);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            for (int x = 0; x < n; x++)
                for (int y = 0; y < n; y++)
                    if (cc[i][j] == 1 && cc[x][y] == 2)
                        ans = min(ans, (i-x)*(i-x) + (j-y)*(j-y));
    cout << ans << endl;
    return 0;
}

C. 4005. 取石子游戏

题目链接:https://www.acwing.com/problem/content/4008/

题目大意:每次只能取 \(1,2,k\) 颗石子,最先取完的获胜,问:谁获胜。

解题思路:先搜索打表找规律。

打表的代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 51;

int n, k;
bool vis[maxn], f[maxn];


bool dfs(int x) {
    if (x < 0) return true;
    if (vis[x]) return f[x];
    vis[x] = true;
    if (x == 0) return f[x] = false;
    if (!dfs(x-1) || !dfs(x-2) || !dfs(x-k)) return f[x] = true;
    return f[x] = false;
}

int main() {
    for (k = 3; k <= 40; k++) {
        printf("%2d: ", k);
        memset(vis, 0, sizeof vis);
        for (int i = 1; i < maxn; i++) cout << dfs(i);
        cout << endl;
    }
    return 0;
}

打表结果:

 3: 11101110111011101110111011101110111011101110111011
 4: 11011011011011011011011011011011011011011011011011
 5: 11011011011011011011011011011011011011011011011011
 6: 11011101101110110111011011101101110110111011011101
 7: 11011011011011011011011011011011011011011011011011
 8: 11011011011011011011011011011011011011011011011011
 9: 11011011101101101110110110111011011011101101101110
10: 11011011011011011011011011011011011011011011011011
11: 11011011011011011011011011011011011011011011011011
12: 11011011011101101101101110110110110111011011011011
13: 11011011011011011011011011011011011011011011011011
14: 11011011011011011011011011011011011011011011011011
15: 11011011011011101101101101101110110110110110111011
16: 11011011011011011011011011011011011011011011011011
17: 11011011011011011011011011011011011011011011011011
18: 11011011011011011101101101101101101110110110110110
19: 11011011011011011011011011011011011011011011011011
20: 11011011011011011011011011011011011011011011011011
21: 11011011011011011011101101101101101101101110110110
22: 11011011011011011011011011011011011011011011011011
23: 11011011011011011011011011011011011011011011011011
24: 11011011011011011011011101101101101101101101101110
25: 11011011011011011011011011011011011011011011011011
26: 11011011011011011011011011011011011011011011011011
27: 11011011011011011011011011101101101101101101101101
28: 11011011011011011011011011011011011011011011011011
29: 11011011011011011011011011011011011011011011011011
30: 11011011011011011011011011011101101101101101101101
31: 11011011011011011011011011011011011011011011011011
32: 11011011011011011011011011011011011011011011011011
33: 11011011011011011011011011011011101101101101101101
34: 11011011011011011011011011011011011011011011011011
35: 11011011011011011011011011011011011011011011011011
36: 11011011011011011011011011011011011101101101101101
37: 11011011011011011011011011011011011011011011011011
38: 11011011011011011011011011011011011011011011011011
39: 11011011011011011011011011011011011011101101101101
40: 11011011011011011011011011011011011011011011011011

可以发现:

  • \(k\) 不是 \(3\) 的倍数时,状态是 "110" 循环的。

可以发现,此时若 \(n\) 不是 \(3\) 的倍数则为必胜态;若是 \(3\) 的倍数则为必败态。

而:

  • \(k = 3\) 时,状态是 "1110" 循环的(循环节长度为 \(4\)
  • \(k = 6\) 时,状态是 "1101110" 循环的(循环节长度为 \(7\)
  • \(k = 9\) 时,状态是 "1101101110" 循环的(循环节长度为 \(10\)
  • \(k = 12\) 时,状态是 "1101101101110" 循环的(循环节长度为 \(13\)
  • ……

可以发现,此时我们先让 \(n\) 变为它对 \(k+1\) 取余数的结果,然后判断:\(n \neq k\)\(3 | n\)时,是必败态;否则,必胜态。

示例程序:

#include <bits/stdc++.h>
using namespace std;

int T, n, k;

int main() {
    cin >> T;
    while (T--) {
        cin >> n >> k;
        if (k % 3) puts(n%3 ? "Alice" : "Bob");
        else {
            n %= k+1;
            puts(n == k || n % 3 ? "Alice" : "Bob");
        }
    }
    return 0;
}
posted @ 2022-04-20 09:54  quanjun  阅读(22)  评论(0编辑  收藏  举报