2022蓝桥杯B组C语言解题(上)

这篇博客介绍了五个编程题目,包括九进制转十进制、判断顺子日期、计算刷题天数、灌木修剪问题以及X进制减法。博主通过分析样例和题目要求,给出了简洁的解决方案,并展示了如何计算每个问题的关键点,如进制转换的规律、日期中的顺子检测、刷题计划的计算、灌木生长模式的识别和不同进制减法的最小结果。此外,还讨论了一种可能超时的子矩阵统计方法。
摘要由CSDN通过智能技术生成

目录

试题 A: 九进制转十进制

 试题 B: 顺子日期

试题 C: 刷题统计

 试题 D: 修剪灌木

试题 E: X 进制减法

试题 F: 统计子矩阵 时间限制:


试题 A: 九进制转十进制

本题总分:5 分

【问题描述】 九进制正整数 (2022)9 转换成十进制等于多少?

int main()
{
	printf("%d", 20 + 2 * 9 * 9 * 9);
	return 0;
}
1478

 试题 B: 顺子日期

本题总分:5 分

【问题描述】 小明特别喜欢顺子。顺子指的就是连续的三个数字:123、456 等。顺子日 期指的就是在日期的 yyyymmdd 表示法中,存在任意连续的三位数是一个顺 子的日期。例如 20220123 就是一个顺子日期,因为它出现了一个顺子:123; 而 20221023 则不是一个顺子日期,它一个顺子也没有。小明想知道在整个 2022 年份中,一共有多少个顺子日期。

因为题目中提到的只有123,没说012,所以我认为只有四个(不确定)

/*顺子日期
* 20220123
* 20221123
* 20221230
* 20221231
* 4
*/

试题 C: 刷题统计

时间限制: 1.0s 内存限制: 256.0MB 本题总分:10 分

【问题描述】 小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天 做 a 道题目,周六和周日每天做 b 道题目。请你帮小明计算,按照计划他将在 第几天实现做题数大于等于 n 题?

【输入格式】 输入一行包含三个整数 a, b 和 n.

【输出格式】 输出一个整数代表天数。

【样例输入】 10 20 99

【样例输出】 8

【评测用例规模与约定】

对于 50% 的评测用例,1 ≤ a, b, n ≤ 106 .

对于 100% 的评测用例,1 ≤ a, b, n ≤ 1018 .

 这题我说的想法是用数组把七天中每天的的做题数存起来然后减就行了 

int main()
{
	int a, b, n,day=0,i=0;
		scanf_s("%d %d %d", &a, &b, &n);
		int arr[7] = { a,a,a,a,a,b,b };
		while (n >= 0)
		{
			n -= arr[i];
			i++;
			day++;
			if (i > 6)
				i = 0;
		}
		printf("%d", day);
	return 0;
}

之前没看范围,现在修改一下

int main()
{
	int a, b, n, day = 0, i = 0;
	scanf_s("%d %d %d", &a, &b, &n);
	int arr[7] = { a,a,a,a,a,b,b };
	day += n / (5 * a + 2 * b)*7;
	n %= (5 * a + 2 * b);
	while (n >= 0)
	{
		n -= arr[i];
		i++;
		day++;
	}
	printf("%d", day);
	return 0;
}

 

 试题 D: 修剪灌木

时间限制: 1.0s 内存限制: 256.0MB 本题总分:10 分

【问题描述】 爱丽丝要完成一项修剪灌木的工作。 有 N 棵灌木整齐的从左到右排成一排。爱丽丝在每天傍晚会修剪一棵灌 木,让灌木的高度变为 0 厘米。爱丽丝修剪灌木的顺序是从最左侧的灌木开始, 每天向右修剪一棵灌木。当修剪了最右侧的灌木后,她会调转方向,下一天开 始向左修剪灌木。直到修剪了最左的灌木后再次调转方向。然后如此循环往复。 灌木每天从早上到傍晚会长高 1 厘米,而其余时间不会长高。在第一天的 早晨,所有灌木的高度都是 0 厘米。爱丽丝想知道每棵灌木最高长到多高。

【输入格式】 一个正整数 N ,含义如题面所述。

【输出格式】 输出 N 行,每行一个整数,第行表示从左到右第 i 棵树最高能长到多高。

【样例输入】 3

【样例输出】 4 2 4

【评测用例规模与约定】 对于 30% 的数据,N ≤ 10. 对于 100% 的数据,1 < N ≤ 10000.

这题乍一看好像有一点难度,实际上并不难,找规律就行,每棵树最长高度首先看它所处位置,以此树为中心 ,观察其两端树的个数,选择树多的那端乘2,便是最大高度

int main()
{
	int N,count;
	scanf_s("%d", &N);
	int mid = N / 2;
	for (int i = 1; i <= N; i++)
	{
		if (i <= mid)
		{
			count = (N - i) * 2;
		}
		else
		{
			count = (i-1) * 2;
		}
		printf("%d\n", count);
	 }
	return 0;
}

试题 E: X 进制减法

时间限制: 1.0s 内存限制: 256.0MB 本题总分:15 分

【问题描述】 进制规定了数字在数位上逢几进一。 X 进制是一种很神奇的进制,因为其每一数位的进制并不固定!例如说某 种 X 进制数,最低数位为二进制,第二数位为十进制,第三数位为八进制,则 X 进制数 321 转换为十进制数为 65。 现在有两个 X 进制表示的整数 A 和 B,但是其具体每一数位的进制还不确 定,只知道 A 和 B 是同一进制规则,且每一数位最高为 N 进制,最低为二进 制。请你算出 A − B 的结果最小可能是多少。 请注意,你需要保证 A 和 B 在 X 进制下都是合法的,即每一数位上的数 字要小于其进制。 【

输入格式】

第一行一个正整数 N,含义如题面所述。

第二行一个正整数 Ma,表示 X 进制数 A 的位数。

第三行 Ma 个用空格分开的整数,表示 X 进制数 A 按从高位到低位顺序各 个数位上的数字在十进制下的表示。

第四行一个正整数 Mb,表示 X 进制数 B 的位数。

第五行 Mb 个用空格分开的整数,表示 X 进制数 B 按从高位到低位顺序各 个数位上的数字在十进制下的表示。 请注意,输入中的所有数字都是十进制的。

【输出格式】 输出一行一个整数,表示 X 进制数 A − B 的结果的最小可能值转换为十进 制后再模 1000000007 的结果。

【样例输入】

11

3

10 4 0

3

1 2 0

【样例输出】 94

【样例说明】 当进制为:最低位 2 进制,第二数位 5 进制,第三数位 11 进制时,减法 得到的差最小。此时 A 在十进制下是 108,B 在十进制下是 14,差值是 94。

【评测用例规模与约定】 对于 30% 的数据,N ≤ 10; Ma, Mb ≤ 8. 对于 100% 的数据,2 ≤ N ≤ 1000; 1 ≤ Ma, Mb ≤ 100000; A ≥ B

一开始没算出进制怎么来的,后面根据样例总结出来了

65=1+2*2+3*10*2 

108=0+8+5*10*2

14=2*2+5*1*2

最低位不变直接加,倒数第二位乘最低位的进制加,最高位乘第二位的进制后还要乘二再加。

关于求进制,其实也很简单,二进制不会出现三,三进制不会出现四,要使相减的结果最小,每位都用其最小的进制,那就是本身的数+1,但前提是要先进行比较,比较出两个中其中较大的那个再加

int cmp(int num1, int num2)
{
	return num1 > num2 ? num1:num2;
}
int main()
{
	int N,M1,M2,i,j,count,s1=0,s2=0;
	int m1[100000] = {0};
	int m2[100000] = {0};
	scanf_s("%d", &N);
	scanf_s("%d", &M1);
	for (i = 0; i < M1; i++)
	{
		scanf_s("%d", &m1[i]);
	}
	scanf_s("%d", &M2);
	for (i = 0; i < M2; i++)
	{
		scanf_s("%d", &m2[i]);
	}
	if (M1 >= 1)
	{
		s1 = m1[M1 - 1]; 
	}
	if (M2 >= 1)
	{
		s2 = m2[M2 - 1];
	}
	for (i = M1-1, j = M2-1; i >= 0;i-- )
	{
		count=cmp(m1[i], m2[j])+1;
		if (count < 2)
			count = 2;
		if (i !=1)
			s1 = s1 + count * m1[i - 1];
		else
			s1 = s1 + count * m1[0] * 2;
		if(j!=1)
			s2 = s2 + count * m2[j - 1];
		else
			s2 = s2 + count * m2[0] * 2;
		if (j >= 1)
		j--;
	}
	printf("%d", s1 - s2);
	return 0;

试题 F: 统计子矩阵 时间限制:

1.0s 内存限制: 256.0MB 本题总分:15 分

【问题描述】 给定一个 N × M 的矩阵 A,请你统计有多少个子矩阵 (最小 1 × 1,最大 N × M) 满足子矩阵中所有数的和不超过给定的整数 K?

【输入格式】 第一行包含三个整数 N, M 和 K. 之后 N 行每行包含 M 个整数,代表矩阵 A.

【输出格式】 一个整数代表答案。

【样例输入】

3 4 10

1 2 3 4

5 6 7 8

9 10 11 12

【样例输出】 19

评测用例规模与约定】

对于 30% 的数据,N, M ≤ 20. 对于 70% 的数据,N, M ≤ 100. 对于 100% 的数据,1 ≤ N, M ≤ 500; 0 ≤ Ai j ≤ 1000; 1 ≤ K ≤ 250000000.

这题我想到的是前缀和再枚举,时间复杂度为n^4有点高能过30%,70%可能有点悬

int N, M, i, j, count = 0;
long long K, num;
long long arr[502][502], s[502][502];
int main()
{
	scanf_s("%d %d %lld",&N,&M,&K);
	for (i = 1; i <= N; i++)
	{
		for (j = 1; j <= M; j++)
		{
			scanf_s("%lld", &arr[i][j]);
			s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + arr[i][j];
		}
	}
	for (i = 1; i <= N; i++)
	{
		for (j = 1; j <= M; j++)
		{

			for (int k = 1; k <= i; k++)
			{
				for (int l = 1; l <= j; l++)
				{
					num = s[i][j] - s[i][l - 1] - s[k - 1][j] + s[k - 1][l - 1];
					if (num <= K)
						count++;
				}
			}
		}
	}
	printf("%d", count);
	return 0;
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shany-Ming

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值