【蓝桥杯C++】第十四届蓝桥杯模拟赛(第三期)

一、字母数

  • 问题描述   请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 F)。   请将这个数的十进制形式作为答案提交。 答案提交
      这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

十进制转十六进制:除16取余,判断余数是否为字母,这里无需考虑翻转,不影响结果。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
bool check(int x)
{
    
    
	while(x)
	{
    
    
		if(x%16 <= 9)
			return false;
		else 
			x /= 16; 
	}
	return true;
}
int main()
{
    
    
	int x = 2022;
	while(true)
	{
    
    
		if(check(x))
			break;
		x++;
	 } 
	 cout << x << endl; 
	return 0;
 } 

答案:2730

二、列名

  • 问题描述   在 Excel 中,列的名称使用英文字母的组合。前 26 列用一个字母,依次为 A 到 Z,接下来 26*26 列使用两个字母的组合,依次为 AA 到 ZZ。   请问第 2022 列的名称是什么? 答案提交
      这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个由大写字母组成的字符串,在提交答案时只填写这个字符串,填写多余的内容将无法得分。

很简单,直接excel第一行第一轮输入数字1,然后鼠标一直往左拖到2022列,上方字母即为答案,最后直接输出结果。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
using namespace std;
int main()
{
    
    
	cout << "BYT";
	return 0;
}

三、特殊日期

  • 问题描述   对于一个日期,我们可以计算出年份的各个数位上的数字之和,也可以分别计算月和日的各位数字之和。请问从 1900 年 1 月 1 日至 9999 年 12 月 31 日,总共有多少天,年份的数位数字之和等于月的数位数字之和加日的数位数字之和。
      例如,2022年11月13日满足要求,因为 2+0+2+2=(1+1)+(1+3) 。   请提交满足条件的日期的总数量。 答案提交
      这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

暴力枚举

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
using namespace std;
int days[] = {
    
    0,31,28,31,30,31,30,31,31,30,31,30,31};
//判断是否为闰年 
bool is_leap(int y)
{
    
    
	return y % 400 == 0 || y % 4 == 0 && y % 100 != 0;
}
int daysofMonth(int y ,int m)
{
    
    
	if(m == 2)
		return is_leap(y) + 28; //是闰年则为1+28 = 29天,否为0+28 = 28天 
	return days[m]; 
}
//判断年份数位之和是否等于月和日的个数位之和 
bool check(int x,int y,int z)
{
    
    
	int s1 = 0,s2 = 0;
	while(x){
    
    
		s1 += x%10;
		x /= 10;
	}
	while(y){
    
    
		s2 += y%10;
		y /= 10;
	}
	while(z){
    
    
		s2 += z%10;
		z /= 10;
	}
	return s1 == s2;
}
int main()
{
    
    
	int res = 0;
	//暴力枚举 
	for(int i = 1900;i <= 9999;i++)	{
    
    
		for(int j = 1;j <= 12;j++){
    
    
			for(int k = 1;k <= daysofMonth(i,j);k++){
    
    
				res += check(i,j,k);
			}
		}

	}
	cout << res << endl;
	return 0;
}

答案为:70910

四、最大乘积

  • 问题描述   小蓝有 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 。 答案提交
      这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

双重暴力枚举,将两数之积大于2022的数统计起来,即为答案。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;
int n = 30;
int a[] = {
    
    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()
{
    
    
	int res = 0;
	for(int i = 0;i < n;i++){
    
    
		for(int j = 0;j < i;j++){
    
    
			if(a[i] * a[j] >= 2022)
				res++;
		}
	}
	cout << res << endl;
	return 0;
 } 

答案为:189

五、最大联通

  • 问题描述   小蓝有一个 30 行 60 列的数字矩阵,矩阵中的每个数都是 0 或 1 。   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
      如果从一个标为 1 的位置可以通过上下左右走到另一个标为 1 的位置,则称两个位置连通。与某一个标为 1
    的位置连通的所有位置(包括自己)组成一个连通分块。   请问矩阵中最大的连通分块有多大? 答案提交
      这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

int main()
{
    
    
    puts("148");
    return 0;
}

答案:148

六、星期几

  • 问题描述   给定一天是一周中的哪天,请问 n 天后是一周中的哪天? 输入格式   输入第一行包含一个整数 w,表示给定的天是一周中的哪天,w 为 1 到 6 分别表示周一到周六,w 为 7 表示周日。   第二行包含一个整数 n。 输出格式
      输出一行包含一个整数,表示 n 天后是一周中的哪天,1 到 6 分别表示周一到周六,7 表示周日。 样例输入 6 10 样例输出 2
    评测用例规模与约定   对于所有评测用例,1 <= n <= 1000000。

(w+n)%7判断即可,当等于0时为周日输出七

#include<iostream>
using namespace std;
int main()
{
    
    
	long long n;
	int  w,day;
	cin >> w >> n;  //w为星期,n为天数 
	day = (w+n)%7;
	if(day == 0)
		cout << "7";
	else
		cout << day;
	return 0;
}

七、信号覆盖

  • 问题描述   小蓝有一个 n * m 大小的矩形水域,小蓝将这个水域划分为 n 行 m 列,行数从 1 到 n 标号,列数从 1 到 m 标号。每行和每列的宽度都是单位 1 。   现在,这个水域长满了水草,小蓝要清理水草。   每次,小蓝可以清理一块矩形的区域,从第 r1
    行(含)到第 r2 行(含)的第 c1 列(含)到 c2 列(含)。   经过一段时间清理后,请问还有多少地方没有被清理过。 输入格式
      输入第一行包含两个整数 n, m,用一个空格分隔。   第二行包含一个整数 t ,表示清理的次数。   接下来 t 行,每行四个整数
    r1, c1, r2, c2,相邻整数之间用一个空格分隔,表示一次清理。请注意输入的顺序。 输出格式
      输出一行包含一个整数,表示没有被清理过的面积。 样例输入 2 3 2 1 1 1 3 1 2 2 2 样例输出 2 样例输入 30 20
    2 5 5 10 15 6 7 15 9 样例输出 519 评测用例规模与约定   对于所有评测用例,1 <= r1 <= r2 <= n
    <= 100, 1 <= c1 <= c2 <= m <= 100, 0 <= t <= 100。

数据范围较小,可以暴力枚举所有的点是否被覆盖,一个点是否被信号覆盖可以枚举所有的信号塔。
若有圆 C C C ,圆心为 ( a , b ) (a, b) (a,b) ,半径为 r r r ,则该圆的公式为:
( x − a ) 2 + ( y − b ) 2 = r 2 (x - a)^2 + (y - b)^2 = r^2 (xa)2+(yb)2=r2
根据数学知识可知,将一个点的横纵坐标带入上式

  1. ( x − a ) 2 + ( y − b ) 2 > r 2 (x - a)^2 + (y - b)^2 > r^2 (xa)2+(yb)2>r2 则该点在圆 C C C
  2. ( x − a ) 2 + ( y − b ) 2 = r 2 (x - a)^2 + (y - b)^2 = r^2 (xa)2+(yb)2=r2 则该点在圆 C C C
  3. ( x − a ) 2 + ( y − b ) 2 < r 2 (x - a)^2 + (y - b)^2 < r^2 (xa)2+(yb)2<r2 则该点在圆 C C C
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>

using namespace std;
const int N = 105;
int X[N],Y[N];
int w,h,n,R;
//判断监测点是否这信号塔中 
bool check(int x,int y){
    
    
	for(int i = 0;i < n;i++){
    
    
		int tx = x-X[i],ty = y - Y[i];
		//在圆里面即可被信号覆盖 
		if(tx*tx +ty*ty <= R*R)
			return true;
	} 
	return false;
}
int main()
{
    
    
	cin >> w >> h >> n >> R;
	//输入信号塔的坐标位置 
	for(int i = 0;i < n;i++){
    
    
		cin >> X[i] >> Y[i];
	} 
	//暴力枚举所有的监测点 
	int res = 0; 
	for(int i = 0;i <= w;i++){
    
    
		for(int j = 0;j <= h;j++){
    
    
			res += check(i,j);
		}
	} 
	cout << res << endl;
	return 0;
}

终端测试输入:

6 4 4 2
1 1
2 0
3 3
4 2

输出为:26

猜你喜欢

转载自blog.csdn.net/qq_62775411/article/details/130001028