CSP-J 2024 复赛题解
T1
数据仅有 52,极小的数据范围导致这题只有一个问题:如何简短方便的去重并统计。
我选择了 map 做法:每个输入查找 map 中之前是否记录过此元素,如果记录过则证明已经拥有这张牌,反之则记录并将统计数增加。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int n;
map<string, bool> poker;
int cnt = 0;
int main()
{
cin >> n;
while (n--)
{
string pok;
cin >> pok;
map<string, bool>::iterator f;
f = poker.find(pok);
if (f == poker.end())
{
poker.insert(pair<string, bool> (pok, true));
cnt++;
}
}
cout << 52 - cnt;
return 0;
}
T2
纯模拟,细节把握好即可。
(不要想作者写了 100 行屎山发现写错了。。。)
题面模拟细节摘要:
- 设地图上
.
为空地。 - 若 \(d = 0\),则令 \((x^′, y^′) = (x, y + 1)\),若 \(d = 1\),则令 \((x^′, y^′) = (x + 1, y)\),若 \(d = 2\),则令 \((x^′, y^′) = (x, y - 1)\),若 \(d = 3\),则令 \((x^′, y^′) = (x − 1, y)\),若目前朝向的 \((x^′, y^′)\) 不是空地,则令 \(d^′ = (d + 1) \bmod 4\)。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int T;
int n, m, k;
int x, y, d;
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
int main()
{
cin >> T;
while (T--)
{
cin >> n >> m >> k;
cin >> x >> y >> d;
x--, y--;
char mp[1005][1005];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
cin >> mp[i][j];
}
bool vis[1005][1005];
memset(vis, 0, sizeof(vis));
int moves = 0, cnt = 0;
if (mp[x][y] == '.' && !vis[x][y])
{
vis[x][y] = true;
cnt++;
}
while (moves < k)
{
int nx = x + dx[d];
int ny = y + dy[d];
if (nx >= 0 && nx < n && ny >= 0 && ny < m && mp[nx][ny] == '.')
{
x = nx;
y = ny;
if (!vis[x][y]) {
vis[x][y] = true;
cnt++;
}
}
else
d = (d + 1) % 4;
moves++;
}
cout << cnt << "\n";
}
return 0;
}
T3
思路:分讨
根据特殊性质,我们可以发现:
- 对于 A,我们发现全放
8
就能满足条件。 - 对于 B,此时全放使用个数最多的
8
不能满足,还需要一位,所以我们可以最小化首位数字大小,即填上10
。
根据上述讨论,我们发现解决的核心即为最小化数字位数,全部填入 8
,然后在不增加位数的情况下改变某些数字(前三位)使得总木棍数正好为 \(n\)。
每个 \(n\) 都可以表示为 \(n = 7 \times k - x (0 \le x < 7)\),答案数字位数应为 \(k\)。
然后进行分讨:
0. 不替换,前三位 888
。
- 替换前两位为
10
,前三位108
。 - 替换第一位为
1
,前三位188
。 - 替换前三位为
200
,前三位200
。 - 替换前两位为
20
,前三位208
。 - 替换第一位为
2
,前三位288
。 - 替换第一位为
6
,前三位688
。
由于我使用的全为更改前三位 (因为我懒) 所以答案为两位数的(\(n \le 14\))都被我算出来并特判,具体见代码。
#include <bits/stdc++.h>
using namespace std;
int T, n;
int main()
{
cin >> T;
while (T--)
{
cin >> n;
// 特判
int sth[15] = {-1, -1, 1, 7, 4, 2, 6, 8, 10, 18, 22, 20, 28, 68, 88};
// 分讨
int num[7] = {888, 108, 188, 200, 208, 288, 688};
if (n <= 14)
cout << sth[n] << "\n";
else
{
cout << num[n % 7];
for (int i = 1; i <= (n - 1) / 7 - 2; i++)
cout << 8;
cout << "\n";
}
}
return 0;
}
作者:George0915,转载请注明原文链接:https://www.cnblogs.com/George222/p/18508467