第十一届蓝桥杯(2020)-省赛题解_C/C++__大学A组第二场

目录

        • 感悟总结
        • 一、门牌制作(填空题)
        • 二、既约分数(填空题)
        • 三、蛇形填数(填空题)
        • 四、七段码(填空题)
        • 五、平面分割
        • 六、成绩分析
        • 七、回文日期
        • 八、子串分值
        • 九、荒岛探测
        • 十、字串排序

感悟总结

本文有自己的思路,也有对网络上思路的借鉴,但不保证百分百正确,如有错误不足,希望得到您的指正!

一、门牌制作(填空题)

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

#include
using namespace std;
int ans=0;
void f(int x)
{
	while(x)
	{
		int a=x%10;
		if(a==2) ans++;
		x/=10;
	}
}
int main()
{
	for(int i=1;i<=2020;i++)
		f(i);
	cout<<ans<<endl;
	return 0;	
} //结果:624
二、既约分数(填空题)

如果一个分数的分子和分母的最大公约数是 1,这个分数称为既约分数。
例如,3/4,5/2,1/8,7/1都是既约分数。
请问,有多少个既约分数,分子和分母都是1到2020之间的整数(包括 1和 2020)?

#include
using namespace std;
int ans=0;
int gcd(int a,int b)
{
	return b==0?a:gcd(b,a%b);
}
int main()
{
	for(int i=1;i<=2020;i++)
	{
		for(int j=1;j<=2020;j++)
		{
			if(gcd(i,j)==1) ans++;
		}
	}
	cout<<ans<<endl;
	return 0;	
} 
//结果:2481215
三、蛇形填数(填空题)

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

#include
using namespace std;
int main()
{
	int sum=0,n=0;
	for(int i=1;i<=19;i++)
	{
		n+=4;
		sum+=n;
	}
	cout<<sum+1<<endl;
	return 0;	
} 
四、七段码(填空题)

用next_permutation数组全排列
当有一段亮的时候,个数为7,之后每多一段亮,a数组就要多加一个1,返回check函数cnt函数也要加1,下列代码展示的是有四段亮的时候,
唯一需要注意的是check函数当有四段亮的时候有三种情况不合法,
需要用23-3,分别是1101100,0110110,1011010的情况
第十一届蓝桥杯(2020)-省赛题解_C/C++__大学A组第二场_第1张图片

#include
using namespace std;
int a[7]={0,0,0,1,1,1,1};
//0:a,1:b,2:c,3:d,4:e,5:f,6:g
bool check()
{
	int cnt=0;
	if(a[0]==1){if(a[1]==1||a[5]==1) cnt++;}
	if(a[1]==1){if(a[0]==1||a[6]==1||a[2]==1) cnt++;}
	if(a[2]==1){if(a[1]==1||a[6]==1||a[3]==1) cnt++;}
	if(a[3]==1){if(a[2]==1||a[4]==1) cnt++;}
	if(a[4]==1){if(a[3]==1||a[6]==1||a[5]==1) cnt++;}
	if(a[5]==1){if(a[0]==1||a[6]==1||a[4]==1) cnt++;}
	if(a[6]==1){if(a[1]==1||a[2]==1||a[4]==1||a[5]==1) cnt++;}
	if(cnt==4) return true;
	else return false;
}
int main()
{
	int ans=0;
	do{
		if(check())
		{
			ans++;
			for(int i=0;i<=6;i++)
			{
				cout<<a[i]<<" ";
			}
			cout<<endl;
		}
	}while(next_permutation(a,a+7)); 
	cout<<ans<<endl;
	return 0;
} 
//7+10+16+23-3+19+7+1
五、平面分割
六、成绩分析

【问题描述】
小蓝给学生们组织了一场考试,卷面总分为 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。

#include
using namespace std;
int main()
{
    int n;cin>>n;
    long long sum;
    int t=n;
    int MAX=-1,MIN=101;
    while(t--)
    {
        int a;
        cin>>a;
        sum+=a;
        if(a>MAX) MAX=a;
        if(a<MIN) MIN=a;
    }
    cout<<MAX<<endl;
    cout<<MIN<<endl;
    printf("%.2lf\n",1.0*sum/n);
    
    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
using namespace std;
int a[10],b[10];
bool check(int y,int m,int n){
    if(y%400==0||(y%100!=0&&y%4==0))
    {
        if(m>=1&&m<=12)
        {
            if(m==2&&n<=29&&n>=1)
                return true;
            else if((m==1||m==3||m==5||m==7||m==8||m==10||m==12)&&n<=31&&n>=1)
                return true;
            else if((m==4||m==6||m==9||m==11)&&n<=30&&n>=1)
                return true;
            else return false;
        }
    }
    else
    {
        if(m>=1&&m<=12)
        {
            if(m==2&&n<=28&&n>=1)
                return true;
            else if((m==1||m==3||m==5||m==7||m==8||m==10||m==12)&&n<=31&&n>=1)
                return true;
            else if((m==4||m==6||m==9||m==11)&&n<=30&&n>=1)
                return true;
            else return false;
        }        
    }
    return false;
}
bool huiwei1(int x)//ABCDDCBA
{
	int i=8;
	while(x)
	{
		a[i]=x%10;
		x/=10;
		i--;
	}
	if(a[4]==a[5]&&a[3]==a[6]&&a[2]==a[7]&&a[1]==a[8]) return true;
	else return false;
} 
bool huiwei2(int x)//ABABBABA
{
	int i=8;
	while(x)
	{
		b[i]=x%10;
		x/=10;
		i--;
	}
	if(b[1]==b[3]&&b[3]==b[6]&&b[6]==b[8]&&b[8]==b[1]
	&&b[2]==b[4]&&b[4]==b[5]&&b[5]==b[7]&&b[7]==b[2]) 
		return true;
	else return false;
} 
int main()
{
	int n;
	cin>>n;
	int y=n/10000,m=0,d=0,ans1,ans2;
	while(true)//ABCDDCBA
	{
		y++;
		m=(y%10)*10+((y/10)%10);
		d=((y/100)%10)*10+((y/1000)%10);
		int x=y*10000+m*100+d;
		if(huiwei1(x)&&check(y,m,d)) {
			ans1=x;
			break;
		}
	}
	y=n/10000;
	while(true)//ABABBABA
	{
		y++;
		m=(y%10)*10+((y/10)%10);
		d=(y%10)*10+((y/10)%10);
		int x=y*10000+m*100+d;
		if(huiwei2(x)&&check(y,m,d))  
		{
			ans2=x;
			break;
		}
	}
	cout<<ans1<<endl;
	cout<<ans2<<endl;
	return 0;
}
八、子串分值

【问题描述】
对于一个字符串 S,我们定义 S 的分值 f(S ) 为 S 中出现的不同的字符个 数。例如 f(”aba”) = 2,f(”abc”) = 3, f(”aaa”) = 1。 现在给定一个字符串 S [0…n − 1](长度为 n),请你计算对于所有 S 的非空 子串 S [i… j](0 ≤ i ≤ j < n),f(S [i… j]) 的和是多少。
【输入格式】
输入一行包含一个由小写字母组成的字符串 S。
【输出格式】
输出一个整数表示答案。
【样例输入】
ababc
【样例输出】
28
【样例说明】
子串 f值
a 1
ab 2
aba 2
abab 2
ababc 3
b 1
ba 2
bab 2
babc 3
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。

九、荒岛探测
十、字串排序

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