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 行屎山发现写错了。。。)

题面模拟细节摘要:

  1. 设地图上 . 为空地。
  2. \(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

思路:分讨

根据特殊性质,我们可以发现:

  1. 对于 A,我们发现全放 8 就能满足条件。
  2. 对于 B,此时全放使用个数最多的 8 不能满足,还需要一位,所以我们可以最小化首位数字大小,即填上 10

根据上述讨论,我们发现解决的核心即为最小化数字位数,全部填入 8,然后在不增加位数的情况下改变某些数字(前三位)使得总木棍数正好为 \(n\)

每个 \(n\) 都可以表示为 \(n = 7 \times k - x (0 \le x < 7)\),答案数字位数应为 \(k\)

然后进行分讨:
0. 不替换,前三位 888

  1. 替换前两位为 10,前三位 108
  2. 替换第一位为 1,前三位 188
  3. 替换前三位为 200,前三位 200
  4. 替换前两位为 20,前三位 208
  5. 替换第一位为 2,前三位 288
  6. 替换第一位为 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;
}
posted @ 2024-10-27 15:21  George0915  阅读(34)  评论(0编辑  收藏  举报