2023蓝桥杯校内选拔
2023.11.5
有些仓促,若有错误欢迎指出
1、请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 F)。
// 输出后手动查找一下即可,应该是【2730】
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
int main()
{
for(int i = 2023; i < 3000; i ++)
{
printf("%d == %x\n", i, i);
}
return 0;
}
2、在 Excel 中,列的名称使用英文字母的组合。前 26 列用一个字母,依次为 A 到 Z,接下来 26*26 列使用两个字母的组合,依次为 AA 到 ZZ。
请问第 2022 列的名称是什么?
// 26进制,跑出来之后TYB需要反过来,因为是从低位到高位输出的,ans=【BYT】
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<stack>
using namespace std;
typedef long long LL;
int main()
{
int x = 2022;
while(x)
{
cout << char(x%26+'A'-1) ;
x /= 26;
}
}
3、对于一个日期,我们可以计算出年份的各个数位上的数字之和,也可以分别计算月和日的各位数字之和。请问从 1900 年 1 月 1 日至 9999 年 12 月 31 日,总共有多少天,年份的数位数字之和等于月的数位数字之和加日的数位数字之和。
例如,2022年11月13日满足要求,因为 2+0+2+2=(1+1)+(1+3) 。
请提交满足条件的日期的总数量。
// 直接算就好了 ans=【70910】
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
int days[30] = {0,31,30,31,30,31,30,31,31,30,31,30,31};
LL cal(LL x)
{
LL cnt = 0;
while(x)
{
cnt += x%10;
x /= 10;
}
return cnt;
}
int main()
{
LL ans = 0;
LL sumY = 0, sumD = 0;
for(LL i = 1900; i <= 9999; i ++)
{
sumY = cal(i);
if((i%400 == 0) || (i%4 == 0 && i%100 != 0))
days[2] = 29;
else days[2] = 28;
for(LL j = 1; j <= 12; j ++)
{
for(LL k = 1; k <= days[j]; k ++)
{
sumD = cal(j) + cal(k);
if(sumD == sumY) ans ++;
}
}
}
cout << ans;
return 0;
}
4、小蓝有 30 个数,分别为:99, 22, 51, 63, 72, 61, 20, 88, 40, 21, 63, 30, 11, 18, 99, 12, 93, 16, 7, 53, 64, 9, 28, 84, 34, 96, 52, 82, 51, 77 。
小蓝可以在这些数中取出两个序号不同的数,共有 30*29/2=435 种取法。
请问这 435 种取法中,有多少种取法取出的两个数的乘积大于等于 2022 。
// 从前往后取,不重复 ans=【189】
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
int num[50] = {99, 22, 51, 63, 72, 61, 20, 88, 40, 21, 63, 30, 11, 18, 99, 12, 93, 16, 7, 53, 64, 9, 28, 84, 34, 96, 52, 82, 51, 77};
int main()
{
LL ans = 0;
for(int i = 0; i < 29; i ++)
{
for(int j = i+1 ; j < 30; j ++)
{
if(num[i] * num[j] >= 2022)
ans += 1;
}
}
cout << ans ;
return 0;
}
5、小蓝有一个 30 行 60 列的数字矩阵,矩阵中的每个数都是 0 或 1 。
如果从一个标为 1 的位置可以通过上下左右走到另一个标为 1 的位置,则称两个位置连通。与某一个标为 1 的位置连通的所有位置(包括自己)组成一个连通分块。请问矩阵中最大的连通分块有多大?
// 求最大连通分量,DFS、BFS均可,直接搜索答案,ans=【148】
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long LL;
char maze[65][65] =
{
"110010000011111110101001001001101010111011011011101001111110",
"010000000001010001101100000010010110001111100010101100011110",
"001011101000100011111111111010000010010101010111001000010100",
"101100001101011101101011011001000110111111010000000110110000",
"010101100100010000111000100111100110001110111101010011001011",
"010011011010011110111101111001001001010111110001101000100011",
"101001011000110100001101011000000110110110100100110111101011",
"101111000000101000111001100010110000100110001001000101011001",
"001110111010001011110000001111100001010101001110011010101110",
"001010101000110001011111001010111111100110000011011111101010",
"011111100011001110100101001011110011000101011000100111001011",
"011010001101011110011011111010111110010100101000110111010110",
"001110000111100100101110001011101010001100010111110111011011",
"111100001000001100010110101100111001001111100100110000001101",
"001110010000000111011110000011000010101000111000000110101101",
"100100011101011111001101001010011111110010111101000010000111",
"110010100110101100001101111101010011000110101100000110001010",
"110101101100001110000100010001001010100010110100100001000011",
"100100000100001101010101001101000101101000000101111110001010",
"101101011010101000111110110000110100000010011111111100110010",
"101111000100000100011000010001011111001010010001010110001010",
"001010001110101010000100010011101001010101101101010111100101",
"001111110000101100010111111100000100101010000001011101100001",
"101011110010000010010110000100001010011111100011011000110010",
"011110010100011101100101111101000001011100001011010001110011",
"000101000101000010010010110111000010101111001101100110011100",
"100011100110011111000110011001111100001110110111001001000111",
"111011000110001000110111011001011110010010010110101000011111",
"011110011110110110011011001011010000100100101010110000010011",
"010011110011100101010101111010001001001111101111101110011101"
};
int dir[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
struct pos
{
int x, y;
};
LL bfs(int i, int j)
{
LL cnt = 0;
queue<pos> r;
r.push({i, j});
maze[i][j] = '0';
cnt ++;
while(r.size())
{
pos t = r.front(); r.pop();
for(int i = 0; i < 4; i ++)
{
int x = t.x + dir[i][0];
int y = t.y + dir[i][1];
if(x < 0 || y < 0 || x >= 30 || y >= 60) continue;
if(maze[x][y] == '1')
{
maze[x][y] = '0';
r.push({x,y});
cnt ++;
}
}
}
return cnt;
}
int main()
{
LL ans = 0;
for(int i = 0; i < 30; i ++)
{
for(int j = 0; j < 60; j ++)
{
if(maze[i][j] == '1')
ans = max(ans, bfs(i, j));
}
}
cout << ans;
return 0;
}
6、给定一天是一周中的哪天,请问 n 天后是一周中的哪天?
/*
样例输入
6
10
样例输出
2
*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long LL;
int main()
{
LL a, b;
cin >> a >> b;
LL ans = (a+b)%7;
if(ans == 0) ans = 7;
cout << ans;
return 0;
}
7、信号塔覆盖圆形区域,问总共覆盖多少整数点,去重统计即可,数据范围不大
/*
样例输入
10 10 2 5
0 0
7 0
样例输出
57
*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long LL;
int mp[110][110];
int main()
{
LL w, h, t, r;
LL ans = 0;
cin >> w >> h >> t >> r;
while(t--)
{
LL x, y; cin >> x >> y;
for(int i = 0; i <= w; i ++)
{
for(int j = 0; j <= h; j ++)
{
LL dis = (i-x)*(i-x) + (j-y)*(j-y);
if(dis <= r*r && !mp[i][j])
{
ans ++;
mp[i][j] = 1;
}
}
}
}
cout << ans;
return 0;
}
8、清理方形区域,数据范围不大,遍历即可(数据范围大的话用前缀和数组)
/*
样例输入
30 20
2
5 5 10 15
6 7 15 9
样例输出
519
*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long LL;
int mp[110][110];
int main()
{
int n, m, t;
int r1, c1, r2, c2;
LL ans = 0;
cin >> n >> m >> t;
while(t--)
{
cin >> r1 >> c1 >> r2 >> c2;
for(int i = r1; i <= r2; i ++)
{
for(int j = c1; j <= c2; j ++)
{
mp[i][j] = 1;
}
}
}
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= m; j ++)
{
if(!mp[i][j]) ans ++;
}
}
cout << ans;
return 0;
}
9、滑雪,每次向上下左右小于当前的数字滑;
记忆化搜索即可
/*
样例输入
4 5
1 4 6 3 1
11 8 7 3 1
9 4 5 2 1
1 3 2 2 1
样例输出
7
*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long LL;
LL mp[105][105], dp[105][105], ans = 0;
int n, m;
LL solve(int i, int j){
if(dp[i][j]) return dp[i][j];
dp[i][j] = 1;
if(mp[i-1][j] < mp[i][j] && i-1 >= 1)dp[i][j] = max(dp[i][j], solve(i-1, j)+1);
if(mp[i+1][j] < mp[i][j] && i+1 <= n)dp[i][j] = max(dp[i][j], solve(i+1, j)+1);
if(mp[i][j-1] < mp[i][j] && j-1 >= 1)dp[i][j] = max(dp[i][j], solve(i, j-1)+1);
if(mp[i][j+1] < mp[i][j] && j+1 <= m)dp[i][j] = max(dp[i][j], solve(i, j+1)+1);
return dp[i][j];
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
cin >> mp[i][j];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
ans = max(ans, solve(i, j));
cout << ans;
return 0;
}
10、求当前数字前K个和后K个中的最小值;用单调队列或者滑动窗口
/*
样例输入
5
5 2 7 4 3
1
样例输出
2 2 2 3 3
*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long LL;
const int N = 1000010*2, INF = 0x3f3f3f3f;
int n, k;
struct node
{
int w, id;
}a[N];
deque<node> r;
int main()
{
cin >> n;
for(int i = 1; i <= n; i++){
cin >> a[i].w;
a[i].id = i;
}
cin >> k;
for(int i = n+1; i <= n+k; i++)
{
a[i].id = i;
a[i].w = INF;
}
for(int i = 1; i <= n+k; i++)
{
while(r.size() && r.back().w >= a[i].w)
{
r.pop_back();
}
r.push_back(a[i]);
if(r.front().id <= i-2*k-1) r.pop_front();
if(i >= k+1) cout << r.front().w << " ";
}
}
11、给定绳子长度问对折多少次后长度小于1 (每次对折长度变为对折前1/2)
/*
样例输入
256
样例输出
8
样例输入
257
样例输出
9
*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long LL;
int main()
{
double len;
cin >> len;
LL ans = 0;
while(len > 1.0)
{
len /= 2; ans++;
}
cout << ans;
}
12、给定一个由大写字母组成的长度为 n 的字符串,请在字符串中删除 m 个字符,使得剩下的字符串的字典序最小。
用单调栈维护即可
/*
样例输入
7 3
LANQIAO
样例输出
AIAO
*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<stack>
using namespace std;
typedef long long LL;
stack<char> r;
stack<char> ans;
int main()
{
LL n, m;
string s;
cin >> n >> m >> s;
for(int i = 0; i < n; i ++)
{
while(m > 0 && r.size() && r.top() > s[i])
{
r.pop();
m -= 1;
}
r.push(s[i]);
}
while(r.size())
{
ans.push(r.top());
r.pop();
}
while(ans.size())
{
cout << ans.top();
ans.pop();
}
return 0;
}