算法实战:十四届蓝桥杯C语言A组赛题解答

系列文章目录

C:一切开始的地方-CSDN博客

C语言入门1:常见报错以及解决方案1_c语言::报错-CSDN博客

C语言:分支与循环-CSDN博客

C语言:算法实战 && 扫雷实现-CSDN博客

算法入门-----刷爆链表-CSDN博客



前言

本博客记录博主备战蓝桥杯时的刷题分享,也可以用来进行算法实战练习。


A题

小蓝认为如果一个数含有偶数个数位,并且前面一半的数位之和等于后面一半的数位之和,则这个数是他的幸运数字。
例如 2314 是一个幸运数字,因为它有 4 个数位,并且 2 + 3 = 1 + 4 。
现在请你帮他计算从 1 至 100000000 之间共有多少个不同的幸运数字。
本题的结果为一个整数,在提交答案时只输出这个整数,输出多余的内容将无法得分。

本题是填空题,秩只需填入一个结果,采取暴力求解。

#include<stdio.h>

//暴力求解
int main() {
    int ans = 0;
    // 遍历范围为1到100000000的所有数字
    for (int i = 1; i <= 100000000; ++i) {
        int cnt = 0;
        int num = i;
        // 计算当前数字的位数
        while (num > 0) {
            num /= 10;
            cnt++;
        }
        // 如果位数为奇数,则跳过当前数字
        if (cnt % 2 != 0)
            continue;//退出当前循环,进入下一轮循环

        // 计算数位和
        int sum = 0;
        int now = 0;
        num = i;
        while (num > 0) {
            now++;
            int digit = num % 10;//去除个位
            num /= 10;//除10移位
            // 根据数位位置分别累加或减去数位值
            if (now <= cnt / 2)
                sum += digit;//左边数位上的数依次相加
            else
                sum -= digit;//左边加好的和依次减去右边的位数
        }
        // 如果数位和为0,左边数和恰好等于右边数和,则当前数字是幸运数字,计数器递增
        if (sum == 0)
            ans++;
    }
    // 输出幸运数字的数量
    printf("%d\n", ans);

    return 0;
}

输出结果

B题

给定 L, R,问 L ≤ x ≤ R 中有多少个数 x 满足存在整数 y, z 使得 x = y2 − z2。
输入格式
输入一行包含两个整数 L, R,用一个空格分隔。
输出格式
输出一行包含一个整数满足题目给定条件的 x 的数量。
样例输入
1 5
样例输出
4
提示
1 = 12 − 02 ;
3 = 22 − 12 ;
4 = 22 − 02 ;
5 = 32 − 22 。


对于 40 % 的评测用例,LR ≤ 5000 ;
对于所有评测用例,1 ≤ L ≤ R ≤ 109 。

 解题关键在于数学知识:一个数有平方差就是一个数为4的倍数或一个数为奇数。

#include<stdio.h>
int main()
{
    int a, b;
    int count = 0;
    scanf("%d %d", &a, &b);
        for (int i = a; i <= b; i++) {
            if (i % 4 == 0 || i % 2 != 0) count++;
        }

    printf("%d", count);
    return 0;
}

C题

小蓝有一个长度均为 n 且仅由数字字符 0 ∼ 9 组成的字符串,下标从 0 到 n − 1,你可以将其视作是一个具有 n 位的十进制数字 num,小蓝可以从 num 中选出一段连续的子串并将子串进行反转,最多反转一次。小蓝想要将选出的子串进行反转后再放入原位置处得到的新的数字 numnew 满足条件 numnew < num,请你帮他计算下一共有多少种不同的子串选择方案,只要两个子串在 num 中的位置不完全相同我们就视作是不同的方案。
注意,我们允许前导零的存在,即数字的最高位可以是 0 ,这是合法的。

输入格式
输入一行包含一个长度为 n 的字符串表示 num(仅包含数字字符 0 ∼ 9),
从左至右下标依次为 0 ∼ n − 1。
输出格式
输出一行包含一个整数表示答案。
样例输入
210102
样例输出
8
提示
一共有 8 种不同的方案:
1)所选择的子串下标为 0 ∼ 1 ,反转后的 numnew = 120102 < 210102 ;
2)所选择的子串下标为 0 ∼ 2 ,反转后的 numnew = 012102 < 210102 ;
3)所选择的子串下标为 0 ∼ 3 ,反转后的 numnew = 101202 < 210102 ;
4)所选择的子串下标为 0 ∼ 4 ,反转后的 numnew = 010122 < 210102 ;
5)所选择的子串下标为 0 ∼ 5 ,反转后的 numnew = 201012 < 210102 ;
6)所选择的子串下标为 1 ∼ 2 ,反转后的 numnew = 201102 < 210102 ;
7)所选择的子串下标为 1 ∼ 4 ,反转后的 numnew = 201012 < 210102 ;
8)所选择的子串下标为 3 ∼ 4 ,反转后的 numnew = 210012 < 210102 ;


对于 20% 的评测用例,1 ≤ n ≤ 100 ;
对于 40% 的评测用例,1 ≤ n ≤ 1000 ;
对于所有评测用例,1 ≤ n ≤ 5000 。

#include<stdlib.h>
#define size 5000
int main(){
	char arr[size];
	scanf("%s", arr);
	int sz = strlen(arr);
	int count = 0;
	/*外层循环遍历元素,只需要遍历到倒数第二个元素
	内层循环会遍历a[i]之后的元素与之进行比较*/
	for (int i = 0; i < sz - 1; i++) {
		for (int j = i + 1; j < sz; j++) {
			if (arr[i] > arr[j]) { 
				count++; }
			else if (arr[i] == arr[j]) {
				int temp1 = i;
				int temp2 = j;
				//进入循环寻找逆序
//循环很重要(博主因为循环条件好久才跑出正确结果)
				while (temp1 < temp2) {
					temp1++;
					temp2--;
					if (arr[temp1] > arr[temp2]) {
						count++;
						break;
					}
					else if (arr[temp1] < arr[temp2])
					{
						break;
					}
				}
					
			}
		}
	}
	printf("%d", count);
	return 0;
}

 D题

给定一棵树,结点由 1 至 n 编号,其中结点 1 是树根。树的每个点有一个颜色 Ci。
如果一棵树中存在的每种颜色的结点个数都相同,则我们称它是一棵颜色平衡树。
求出这棵树中有多少个子树是颜色平衡树。
输入格式
输入的第一行包含一个整数 n ,表示树的结点数。
接下来 n 行,每行包含两个整数 Ci , Fi,用一个空格分隔,表示第 i 个结点的颜色和父亲结点编号。
特别地,输入数据保证 F1 为 0 ,也即 1 号点没有父亲结点。保证输入数据是一棵树。
输出格式
输出一行包含一个整数表示答案。
样例输入
6
2 0
2 1
1 2
3 3
3 4
1 4
样例输出
4
提示
编号为 1, 3, 5, 6 的 4 个结点对应的子树为颜色平衡树。


对于 30% 的评测用例,n ≤ 200,Ci ≤ 200 ;
对于 60% 的评测用例,n ≤ 5000,Ci ≤ 5000 ;
对于所有评测用例,1 ≤ n ≤ 200000,1 ≤ Ci ≤ 200000,0 ≤ Fi < i 。

E题

题目描述

小蓝正在一个瓜摊上买瓜。瓜摊上共有 n 个瓜,每个瓜的重量为 Ai 。

小蓝刀功了得,他可以把任何瓜劈成完全等重的两份,不过每个瓜只能劈一刀。

小蓝希望买到的瓜的重量的和恰好为 m 。

请问小蓝至少要劈多少个瓜才能买到重量恰好为 m 的瓜。如果无论怎样小蓝都无法得到总重恰好为 m 的瓜,请输出 −1 。

输入格式

输入的第一行包含两个整数 n, m,用一个空格分隔,分别表示瓜的个数和小蓝想买到的瓜的总重量。

第二行包含 n 个整数 Ai,相邻整数之间使用一个空格分隔,分别表示每个瓜的重量。

输出格式

输出一行包含一个整数表示答案。

样例输入

复制

3 10
1 3 13

样例输出

复制

2

 F题

有一个局域网,由 n 个设备和 m 条物理连接组成,第 i 条连接的稳定性为wi 。

对于从设备 A 到设备 B 的一条经过了若干个物理连接的路径,我们记这条路径的稳定性为其经过所有连接中稳定性最低的那个。

我们记设备 A 到设备 B 之间通信的稳定性为 A 至 B 的所有可行路径的稳定性中最高的那一条。

给定局域网中的设备的物理连接情况,求出若干组设备 xi 和 yi 之间的通信稳定性。如果两台设备之间不存在任何路径,请输出 −1 。

输入格式

输入的第一行包含三个整数 n, m, q ,分别表示设备数、物理连接数和询问数。

接下来 m 行,每行包含三个整数 ui , vi ,wi ,分别表示 ui 和 vi 之间有一条稳定性为 wi 的物理连接。

接下来 q 行,每行包含两个整数 xi , yi ,表示查询 xi 和 yi 之间的通信稳定性。

输出格式

输出 q 行,每行包含一个整数依次表示每个询问的答案。

样例输入

复制

5 4 3
1 2 5
2 3 6
3 4 1
1 4 3
1 5
2 4
1 3

样例输出

复制

-1
3
5

提示

对于 30% 的评测用例,n, q ≤ 500,m ≤ 1000 ;

对于 60% 的评测用例,n, q ≤ 5000,m ≤ 10000 ;

对于所有评测用例,2 ≤ n, q ≤ 105,1 ≤ m ≤ 3 × 105,1 ≤ ui , vi , xi , yi ≤ n,

1 ≤ wi ≤ 106,ui ≠ vi,xi ≠ yi 。


总结

后三题都是暴力求解,还没有找到更好的解法,后续会更新找到的解法~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值