2020第十一届蓝桥杯软件类省赛第二场C/C++ 大学 C 组

连着好几天找C/C++ 大学C组的题解愣是没找到根本没人写,所以就写一篇啦。

本文题目是网上搜集来的,代码今天边回忆边写的,欢迎指正错误。

现场写了8道,D没写出来,I太长没看也没写出来,J是O(n2)骗分。

祈福省一  ^_^

 

目录

​​​​​​​​​​​​​​

试题 A: 约数个数

试题 B: 门牌制作

试题 C: 跑步锻炼

试题 D: 平面分割

试题 E: 蛇形填数

试题 F: 成绩统计

试题 G: 单词分析

试题 H: 数字三角形

试题 I: 作物杂交

试题 J: 字串分值和


试题 A: 约数个数

【问题描述】

对于一个整数,能整除这个整数的数称为这个数的约数。
例如:1, 2, 3, 6 都是 6 的约数。
请问 78120 有多少个约数。

【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

【题解】

答案 :96

//
// Created by shaobaitao on 2020/10/21.
// 约数个数
#include <iostream>
using namespace std;
int main() {
    int ans=0;
    for (int i = 1; i <= 78120; ++i) {
        if(78120%i==0){
            ans++;
        }
    }
    cout<<ans;
    return 0;
}
//96

试题 B: 门牌制作

【问题描述】
小蓝要为一条街的住户制作门牌号。
这条街一共有 2020 位住户,门牌号从 1 到 2020 编号。
小蓝制作门牌的方法是先制作 0 到 9 这几个数字字符,最后根据需要将字
符粘贴到门牌上,例如门牌 1017 需要依次粘贴字符 1、 0、 1、 7,即需要 1 个
字符 0, 2 个字符 1, 1 个字符 7。
请问要制作所有的 1 到 2020 号门牌,总共需要多少个字符 2?

【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

【题解】

答案 :624

对每一个门牌数字每位判断就行,我用的itoa,用%也行

//
// Created by shaobaitao on 2020/10/21.
// 门牌制作
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
int main() {
    int ans=0;
    for (int i = 1; i <= 2020; ++i) {
        char s[10];
        itoa(i,s,10);
        for (int j = 0; j < strlen(s); ++j) {
            if(s[j]=='2'){
                ans++;
            }
        }
    }
    cout<<ans;
    return 0;
}
//624

试题 C: 跑步锻炼

【问题描述】
小蓝每天都锻炼身体。
正常情况下,小蓝每天跑 1 千米。如果某天是周一或者月初(1 日),为了
激励自己,小蓝要跑 2 千米。如果同时是周一或月初,小蓝也是跑 2 千米。
小蓝跑步已经坚持了很长时间,从 2000 年 1 月 1 日周六(含)到 2020 年
10 月 1 日周四(含)。请问这段时间小蓝总共跑步多少千米?

【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

【题解】

答案 :8879

这题目有人用Excel看微博真有人拉了几千行,有手算,有代码模拟。

我思路是算出总天数和总星期一数和总月初数和又是星期一又是月初数

然后答案=总天数+总星期一数+总月初数-又星期一又月初数

总天数我是用win7计算器日期计算得出7580,Excel用datedif函数也可以得出

总星期一数我是简单编了个程用总天数7580循环一遍判断星期一得出总星期一数1083

总月初脑算20年*12月+10个月=250

又是星期一又是月初数我是win7右下角日历一页一页的翻了250页记下来有34天

7580+1083+250-34=8879

以下今天晚上补的代码

//
// Created by shaobaitao on 2020/10/21.
// 跑步锻炼
#include <iostream>
using namespace std;
int main() {
    int calendar[]={0,31,28,31,30,31,30,31,31,30,31,30,31};//平年日历 0不用
    int week=6;//某天是星期几 初始2000年1月1日为星期六  6=星期六 1=星期一 7=星期天
    int mondays=0;//总共有多少个星期一
    int first_of_month=0;//总共有多少个月初
    int mondays_and_first_of_month=0;//总共有多少个又是星期一又是月初
    int total_days=0;//2000/1/1到2020/10/1总天数

    for (int year=2000; year <= 2020; ++year) {
        for (int month=1; month <= 12; ++month) {
            for (int day=1; day <= calendar[month]; ++day) {
                //从2000/1/1循环模拟到2020/10/1

                if(week==1) mondays++;//如果是星期一
                if(day==1) first_of_month++;//如果是月初
                if(week==1&&day==1) mondays_and_first_of_month++;//如果是星期一又月初

                total_days++;
                week=week%7+1;

                if((year%400==0||year%4==0&&year%100!=0)&&month==2&&day==28){
                    //如果是闰年且是2月且为28号
                    total_days++;//把29号加上
                    week=week%7+1;//
                    if(week==1) mondays++;
                    //判断如果是星期一就++  真有一天是闰年2月29号又是星期1
                }
                if(year==2020&&month==10&&day==1){//end date
                    int ans=total_days+mondays+first_of_month-mondays_and_first_of_month;
                    //答案=总天数+总星期一+总月初-总又星期一又月初
                    cout<<ans;
//                    cout<<total_days<<" "<<mondays<<" "<<first_of_month<<" "<<mondays_and_first_of_month;
                    return 0;
                }
            }
        }
    }
}
//8879

试题 D: 平面分割

【问题描述】
20条直线和20个圆最多能把一个平面分割成多少部分?

【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

【题解】

答案 :我没做出来 有大佬分析的1391

https://www.zhihu.com/question/426034179

试题 E: 蛇形填数

【问题描述】

如下图所示,小明用从 1 开始的正整数“蛇形”填充无限大的矩阵。
1 2 6 7 15 :::
3 5 8 14 :::
4 9 13 :::
10 12 :::
11 :::
:::
容易看出矩阵第二行第二列中的数是 5。请你计算矩阵中第 20 行第 20 列
的数是多少 ?

【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

【题解】

答案 :761

直接二维数组模拟出来然后输出第20行20列

//
// Created by shaobaitao on 2020/10/21.
// 蛇形填数
#include <iostream>
using namespace std;
int main() {
    int a[60][60]={0};
    int t=1;
    int n=20;
    for (int i = 0; i <60 ; ++i) {
        if(i%2==0){
            for (int j = 0; j <= i; ++j) {
                a[i][j]=t++;
            }
        }
        else{
            for (int j = i; j >= 0; --j) {
                a[i][j]=t++;
            }
        }
    }
//    for (int i = 0; i <60 ; ++i) {
//        for (int j = 0; j <= i; ++j) {
//            cout<<a[i][j]<<" ";
//        }
//        cout<<endl;
//    }
    cout<<a[(n-1)*2][n-1];
    return 0;
}
//761

试题 F: 成绩统计

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

【问题描述】

小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是一个 0 到 100 的整数。
如果得分至少是 60 分,则称为及格。如果得分至少为 85 分,则称为优秀。
请计算及格率和优秀率,用百分数表示,百分号前的部分四舍五入保留整数。
【输入格式】
输入的第一行包含一个整数 n,表示考试人数。
接下来 n 行,每行包含一个 0 至 100 的整数,表示一个学生的得分。
【输出格式】
输出两行,每行一个百分数,分别表示及格率和优秀率。百分号前的部分四舍五入保留整数。
【样例输入】

7
80
92
56
74
88
100
0

【样例输出】

71%
43%

【评测用例规模与约定】
对于 50% 的评测用例,1 ≤ n ≤ 100。
对于所有评测用例,1 ≤ n ≤ 10000。

【题解】

//
// Created by shaobaitao on 2020/10/21.
// 成绩统计
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
int main() {
    int n;
    vector<int> a;
    int sixty=0,eighty_five=0;
    cin>>n;
    for (int i = 0; i < n; ++i) {
        int t;
        cin>>t;
        if(t>=60) sixty++;
        if(t>=85) eighty_five++;
        a.push_back(t);
    }
    double pass_rate=sixty*1.0/a.size()*100;
    double excellence_rate=eighty_five*1.0/a.size()*100;
    printf("%.f%%\n%.f%%",pass_rate,excellence_rate);
    return 0;
}

试题 G: 单词分析

时间限制: 1.0s 内存限制: 512.0MB
本题总分:20 分

【问题描述】

小蓝正在学习一门神奇的语言,这门语言中的单词都是由小写英文字母组成,有些单词很长,远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词,他准备不再完全记忆这些单词,而是根据单词中哪个字母出现得最多来分辨单词。
现在,请你帮助小蓝,给了一个单词后,帮助他找到出现最多的字母和这个字母出现的次数。
【输入格式】
输入一行包含一个单词,单词只由小写英文字母组成。
【输出格式】
输出两行,第一行包含一个英文字母,表示单词中出现得最多的字母是哪个。如果有多个字母出现的次数相等,输出字典序最小的那个。
第二行包含一个整数,表示出现得最多的那个字母在单词中出现的次数。
【样例输入】

lanqiao

【样例输出】

a
2

【样例输入】

longlonglongistoolong

【样例输出】

o
6

【评测用例规模与约定】
对于所有的评测用例,输入的单词长度不超过 1000。

【题解】

注意如果有多个字母出现的次数相等,输出字典序最小的那个。

//
// Created by shaobaitao on 2020/10/21.
// 单词分析
#include <iostream>
using namespace std;
int main() {
    string a;
    cin>>a;
    int s[26]={0};
    for (int i = 0; i < a.length(); ++i) {
        s[a[i]-97]++;
    }
    int max=0;
    char max_char;
    for (int i = 25; i >= 0; --i) {
        if(s[i]>=max){
            max=s[i];
            max_char=i+97;
        }
    }
    cout<<max_char<<endl<<max;
    return 0;
}

 

试题 H: 数字三角形

时间限制: 1.0s 内存限制: 512.0MB
本题总分:20 分

【问题描述】

上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。
对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。
路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。
【输入格式】
输入的第一行包含一个整数 N (1 < N ≤ 100),表示三角形的行数。下面的N 行给出数字三角形。数字三角形上的数都是 0 至 100 之间的整数。
【输出格式】
输出一个整数,表示答案。
【样例输入】

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

【样例输出】

27

【题解】

多记录一下左右步数就可以了,最后一行取max并且步数差不大于一

//
// Created by shaobaitao on 2020/10/21.
// 数字三角形
#include <iostream>
#include <math.h>
using namespace std;
struct node{
    int value,right,left;
};
int main() {
    node a[105][105]={0};
    int n;
    cin>>n;

    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= i; ++j) {
            cin>>a[i][j].value;
        }
    }
    for (int i = 2; i <= n; ++i) {
        for (int j = 1; j <= i; ++j) {
            if(a[i-1][j-1].value>a[i-1][j].value){
                a[i][j].value+=a[i-1][j-1].value;
                a[i][j].right+=a[i-1][j-1].right+1;
                a[i][j].left+=a[i-1][j-1].left;
            }
            else{
                a[i][j].value+=a[i-1][j].value;
                a[i][j].right+=a[i-1][j].right;
                a[i][j].left+=a[i-1][j].left+1;
            }
        }

    }

    int max=0;
    for (int i = 0; i < n; ++i) {
        if(a[n][i].value>max&&abs(a[n][i].left-a[n][i].right)<=1){
            max=a[n][i].value;
        }
    }
    cout<<max;
//    for (int i = 1; i <= n; ++i) {
//        for (int j = 1; j <= i; ++j) {
//            cout<<a[i][j].value<<" ";
//            cout<<a[i][j].left<<a[i][j].right<<" ";
//        }
//        cout<<endl;
//    }
    return 0;
}

试题 I: 作物杂交

时间限制: 1.0s 内存限制: 512.0MB
本题总分:25 分

【问题描述】

作物杂交是作物栽培中重要的一步。已知有 N 种作物 (编号 1 至 N ),第i 种作物从播种到成熟的时间为 Ti。作物之间两两可以进行杂交,杂交时间取两种中时间较长的一方。如作物 A 种植时间为 5 天,作物 B 种植时间为 7 天,则 AB 杂交花费的时间为 7 天。作物杂交会产生固定的作物,新产生的作物仍然属于 N 种作物中的一种。
初始时,拥有其中 M 种作物的种子 (数量无限,可以支持多次杂交)。同时可以进行多个杂交过程。求问对于给定的目标种子,最少需要多少天能够得到。
如存在 4 种作物 ABCD,各自的成熟时间为 5 天、7 天、3 天、8 天。初始拥有 AB 两种作物的种子,目标种子为 D,已知杂交情况为 A × B → C,
A × C → D。则最短的杂交过程为:

  • 第 1 天到第 7 天 (作物 B 的时间),A × B → C。
  • 第 8 天到第 12 天 (作物 A 的时间),A × C → D。

花费 12 天得到作物 D 的种子。
【输入格式】
输入的第 1 行包含 4 个整数 N, M, K, T,N 表示作物种类总数 (编号 1 至N),M 表示初始拥有的作物种子类型数量,K 表示可以杂交的方案数,T 表示目标种子的编号。
第 2 行包含 N 个整数,其中第 i 个整数表示第 i 种作物的种植时间Ti(1 ≤ Ti ≤ 100)。
第 3 行包含 M 个整数,分别表示已拥有的种子类型 Kj(1 ≤ Kj ≤ M),Kj两两不同。
第 4 至 K + 3 行,每行包含 3 个整数 A, B,C,表示第 A 类作物和第 B 类作物杂交可以获得第 C 类作物的种子。
【输出格式】
输出一个整数,表示得到目标种子的最短杂交时间。
【样例输入】

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

【样例输出】

16

【样例说明】

  • 第 1 天至第 5 天,将编号 1 与编号 2 的作物杂交,得到编号 3 的作物种子。
  • 第 6 天至第 10 天,将编号 1 与编号 3 的作物杂交,得到编号 4 的作物种子。
  • 第 6 天至第 9 天,将编号 2 与编号 3 的作物杂交,得到编号 5 的作物种子。
  • 第 11 天至第 16 天,将编号 4 与编号 5 的作物杂交,得到编号 6 的作物种子。

总共花费 16 天。
【评测用例规模与约定】
对于所有评测用例,1 ≤ N ≤ 2000, 2 ≤ M ≤ N, 1 ≤ K ≤ 100000, 1 ≤ T ≤ N,保证目标种子一定可以通过杂交得到。

【题解】 

本题字太多没看,现场没写出来

隔壁Java C组有写的

https://blog.csdn.net/weixin_48598155/article/details/109133151

https://blog.csdn.net/YCCX_LHH21/article/details/109138143

试题 J: 字串分值和

在这里插入图片描述

【题解】 

现场是用如下代码O(n2)骗分的

//
// Created by shaobaitao on 2020/10/21.
// 子串分值和
#include <iostream>
#include <set>
#include <string>
using namespace std;
int check(string t){
    set<char> a;
    for (int i = 0; i < t.length(); ++i) {
        a.insert(t[i]);
    }
    return a.size();
}
int main() {
    string s;
    cin>>s;
    long long ans=0;
    for (int i = 0; i < s.length(); ++i) {
        for (int j = 1; j <= s.length()-i; ++j) {
            string t=s.substr(i,j);
            ans+=check(t);
        }
    }
    cout<<ans;
    return 0;
}

满分O(n)代码如下

作者找不到了...

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
string str;
ll last[26];	//记录26个字母上一次出现的位置 
ll ans=0;
int main(){	
	for(int i=0;i<26;i++)
		last[i]=-1;
	cin>>str;
	ll len=str.size(); 
	for(ll i=0;i<len;i++){
		ans+=(i-last[str[i]-'a'])*(len-i);
		last[str[i]-'a']=i;
	}
	cout<<ans<<endl;
	return 0;
}

 

  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值