蓝桥杯省赛2020年第十一届C/C++ A组第二场编程题待更新

第六题:成绩统计
题目描述

小蓝给学生们组织了一场考试,卷面总分为100 分,每个学生的得分都是一个0 到100 的整数。请计算这次考试的最高分、最低分和平均分。
【输入格式】 输入的第一行包含一个整数n,表示考试人数。 接下来n 行,每行包含一个0 至100 的整数,表示一个学生的得分。

【输出格式】 输出三行。 第一行包含一个整数,表示最高分。 第二行包含一个整数,表示最低分。
第三行包含一个实数,四舍五入保留正好两位小数,表示平均分。

【样例输入】 7 80 92 56 74 88 99 10 【样例输出】 99 10
71.29 【评测用例规模与约定】 对于50% 的评测用例, 1 ≤ n ≤ 100。 对于所有评测用例,1 ≤ n ≤10000。

#include 
#include 
#include 
#include 
using namespace std;


int main(){
     
	int n;
	cin >> n;
	int min=0x3f3f3f3f;
	int max=0;
	double sum =0;
	int temp;
	for(int i=0; i<n; i++){
     
		scanf("%d",&temp);
		if(temp<min) min = temp;
		if(temp>max) max = temp;
		sum += temp;
	}
	sum/=100.0;
	sum =  (long long)(sum*100 +0.5) * 1.0 /n;
	printf("%d\n%d\n%.2f\n",max,min,sum);
	return 0; 
} 

第七题:回文日期
题目描述

2020 年春节期间,有一个特殊的日期引起了大家的注意:2020年2月2日。因为如果将这个日期按“yyyymmdd” 的格式写成一个8
位数是20200202, 恰好是一个回文数。我们称这样的日期是回文日期。 有人表示20200202 是“千年一遇”
的特殊日子。对此小明很不认同,因为不到2年之后就是下一个回文日期:20211202 即2021年12月2日。 也有人表示20200202
并不仅仅是一个回文日期,还是一个ABABBABA型的回文日期。对此小明也不认同,因为大约100 年后就能遇到下一个ABABBABA
型的回文日期:21211212 即2121 年12 月12 日。算不上“千年一遇”,顶多算“千年两遇”。 给定一个8
位数的日期,请你计算该日期之后下一个回文日期和下一个ABABBABA型的回文日期各是哪一天。

【输入格式】 输入包含一个八位整数N,表示日期。

【输出格式】 输出两行,每行1 个八位数。第一行表示下一个回文日期,第二行表示下 一个ABABBABA 型的回文日期。

【样例输入】 20200202 【样例输出】 20211202 21211212 【评测用例规模与约定】 对于所有评测用例,10000101
≤ N ≤ 89991231,保证N 是一个合法日期的8位数表示

代码

#include 
#include 
#include 
#include 
#include 
using namespace std;
int months[]={
     0,31,28,31,30,31,30,31,31,30,31,30,31};
bool judge(int fi){
     
	int year = fi/10000;
	int month = fi/100%100;
	int day = fi%100;
	if(month<=0||month>12) return false;
	if(day==0 || ( month!=2&&day>months[month] ) ) return false;
	if(month == 2){
     
		int leap=0;
		if( (year%4==0 && year%100!=0) || year%400==0) leap=1;
		if(day > 28+leap) return false;
	}
	return true;
}

int main(){
     
	int  n,ans1=0,ans2=0;
	cin >> n;
	for(int i=n+1; i<=899912310; i++){
     
		if(!judge(i)) continue;
		int temp =i;
		int fi =0;//翻转 
		while(temp){
     
			int t = temp % 10;
			fi = fi*10 + t;
			temp /= 10;
		}
		if(i==fi){
     	
			if(ans1==0) ans1 = i;
			if(i%10==i/100%10 && i/10%10==i/1000%10 && i%10!=i/10%10){
     
				ans2=i;
				break;
			}
		}
	}
	cout<<ans1<<endl<<ans2<<endl;
	return 0; 
} 

第八题 子串分值
题目描述

对于一个字符串S,我们定义S 的分值 f(S) 为S中恰好出现一次的字符个数。例如f (”aba”) = 1,f (”abc”) = 3,
f (”aaa”) = 0。 现在给定一个字符串S[0…n-1](长度为n),请你计算对于所有S的非空子串S[i…j](0 ≤ i ≤ j
< n), f (S[i… j]) 的和是多少。

【输入格式】 输入一行包含一个由小写字母组成的字符串S。

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

【样例输入】 ababc 【样例输出】 21 【样例说明】 子串f值:

a 1 ab 2 aba 1 abab 0 ababc 1 b 1 ba 2 bab 1 babc 2 a 1 ab 2 abc 3 b 1
bc 2 c 1 【评测用例规模与约定】 对于20% 的评测用例,1 ≤ n ≤ 10; 对于40% 的评测用例,1 ≤ n ≤ 100;
对于50% 的评测用例,1 ≤ n ≤ 1000; 对于60% 的评测用例,1 ≤ n ≤ 10000; 对于所有评测用例,1 ≤ n ≤
100000。

暴力代码

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 1e5+10;
int num[255];
int cal(string str){
     
	int len = str.length();
	int re=0;
	for(int i=0; i<len; i++){
     
		num[str[i]]++;
	}
	for(int i=0; i<len; i++){
     
		if(num[str[i]]==1) re++;
	}
	return re;
}
int main(){
     
	string str;
	cin >> str;
	int ans=0;
	int len = str.length();
	 for(int i=0; i<len; i++){
     
	 	for(int j=1; j<=len-i; j++){
     
	 		memset(num,0,sizeof(num));
	 		ans += cal(str.substr(i,j));
		 }
	 }
	 cout << ans << endl;
	return 0;
}

新思路:记录每个位置内字母的上一次和下一次的位置,相乘就是该位置对整体的贡献值

#include
using namespace std;
const int N = 1e5+10;
typedef long long ll;
char str[N];
int pre[N]; // pre[i]记录第几个位置内的字母上一次出现的位置
int nex[N]; // nex[i]记录第i个位置的字母下一次出现的位置
int h[26]; // 每一次更新a-z字母出现的下标(下标从1开始,表示第几个位置)
ll ans;
int main(){
     
    scanf("%s",str + 1); // 从下标为1开始输入字符串
    int len = strlen(str + 1);
    for(int i=1;i<=len;i++)
    {
     
        pre[i] = 1; // i - pre[i]如果该字母在前面没有出现过 左边间隔+ 1 == i - pre[i]
        nex[i] = len; // 如果该位置字母在后面没有出现过 右边间隔+ 1 == nex[i] - 1,但删掉这一句好像也行
    }
    for(int i=1;i<=len;i++){
     
        int t = str[i] - 'a'; // 用下标表示字母 a-0 b-1 c-2 d-3 e-4.....
        pre[i] = h[t];  // z这里有个技巧可以看到有两个t每次循环都在记录某一个字母新出现的位置,而这里恰好是在h[t]更新之前把h[t]赋给pre[i]-----记录第几个位置内的字母上一次出现的位置
        h[t] = i;
    }
    for(int i=0;i<26;i++) h[i] = len+1;
    for(int i=len;i>=1;i--){
     
        int t = str[i] - 'a';
        nex[i] = h[t]; // 这里同理,这里每个位置都会更新,如果没有出现下一个同样的字母,默认下一个为len+1
        h[t] = i;
    }
    for(int i=1;i<=len;i++)
    {
     
        ans+=(ll)(i-pre[i])*(nex[i]-i);
    }
    cout<<ans<<endl;
    return 0;
}

你可能感兴趣的:(蓝桥杯)