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;
}