2020蓝桥杯C++B组省赛

本文通过A到H七个编程题目,展示了如何使用暴力枚举、寻找规律等方法解决复杂问题。涉及全排列、既约分数、蛇形填数、日期计算、七段码、成绩统计、回文日期和子串分值和等算法,深入浅出地探讨了编程中的常见策略和技巧。
摘要由CSDN通过智能技术生成

A.门牌制作

思路:暴力枚举

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	int j,ans=0;
	for(int i=1;i<=2020;i++)
	{
		j=i;
		while(j!=0)
		{
			if(j%10==2)
				ans++;
			j/=10;
		}
	}
	cout<<ans<<endl;
	return 0;
}

答案:624

 

B.既约分数

思路:还是暴力

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	int i,j,ans=0;
	for(i=1;i<=2020;i++)
	{
		for(j=1;j<=2020;j++)
		{
			if(__gcd(i,j)==1)
				ans++;
		}
	}
	cout<<ans<<endl;
	return 0;
}

答案:2481215

 

C.蛇形填数

思路:找规律

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	int a=1,b=4;
	for(int i=2;i<=20;i++)
	{
		a+=b;
		b+=4;
	}
	cout<<a<<endl;
	return 0;
}

答案:761

 

D.跑步锻炼

思路:典型的日期问题,三重for循环,判断日期时注意简单写法

#include<iostream>
#include<algorithm>
using namespace std;
int judge(int year)
{
	if(year%4==0&&year%100!=0||year%400==0)
		return 1;
	return 0;
}
int main()
{
	int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
	int y,m,d;
	int w=6;
	int ans=0;
	for(y=2000;y<=2020;y++)
	{
		for(m=1;m<=12;m++)
		{
			for(d=1;d<=day[m]+((m==2)?judge(y):0);d++)
			{
				ans++;
				if(w==1||d==1)
					ans++;		
				w=w%7+1;
				if(y==2020&&m==10&&d==1)
					cout<<ans;
			}
		}
	}
    return 0;
}

答案:8879

 

E.七段码

思路:半年过去了,记得比赛现场好像是现数的,当时想不出思路有点慌,就直接上手数了...   欠下的总是要还的... 

对1—7进行全排列,由于发光的二极管数量不定,对每一个排列数,截取它的前2个、前3个、前4个...前7个数字,分别进行连续性判断(这里没有前1个,因为1个的不用算,直接最后答案加7即可)。若连续,将这几个数字排序后存入set中。对每一个排列数的每一个前缀都处理完(二重循环),最后输出set中的元素个数+7。

代码:

#include<iostream>
#include<algorithm>
#include<set>
using namespace std; 
set<string>s;
set<string>::iterator it;
string c;
int main()
{
	int i,j,n=7;
	int a[7]={1,2,3,4,5,6,7};
	do
	{
		for(i=0;i<6;i++)
		{
			int book=1;
			if(a[i]==1&&a[i+1]!=6&&a[i+1]!=2)	book=0;
			if(a[i]==2&&a[i+1]!=1&&a[i+1]!=3&&a[i+1]!=7)	book=0;
			if(a[i]==3&&a[i+1]!=2&&a[i+1]!=7&&a[i+1]!=4)	book=0;
			if(a[i]==4&&a[i+1]!=3&&a[i+1]!=5)	book=0;
			if(a[i]==5&&a[i+1]!=4&&a[i+1]!=6&&a[i+1]!=7)	book=0;
			if(a[i]==6&&a[i+1]!=1&&a[i+1]!=5&&a[i+1]!=7)	book=0;
			if(a[i]==7&&a[i+1]!=2&&a[i+1]!=3&&a[i+1]!=5&&a[i+1]!=6)	book=0;
			if(book==0)
				break;
			c.clear();
			for(j=0;j<=i+1;j++)
				c+='0'+a[j];
			sort(c.begin(),c.end());
			s.insert(c);
		}
	}
	while(next_permutation(a,a+n));
	
	cout<<s.size()+7<<endl;
	for(it=s.begin();it!=s.end();it++)
		cout<<*it<<endl;
		
	return 0;
}

答案:80

 

F:成绩统计

思路:水题

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std; 
int main()
{
	int n,i,x,a=0,b=0;
	cin>>n;
	for(i=0;i<n;i++)
	{
		cin>>x;
		if(x>=85)
			a++;
		if(x>=60)
			b++;
	}
	cout<<round(b*100.0/n)<<"%"<<endl;
	cout<<round(a*100.0/n)<<"%"<<endl;
	return 0;
}

 

G:回文日期

思路:一天一天的枚举比较好写,注意日期的一些细节以及简写,注意隐藏条件A!=B。

#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
int judge(int m)
{
	if(m%4==0&&m%100!=0||m%400==0)
		return 1;
	return 0;
}
int judge1(int a,int b,int c)
{
	if(a/1000==c%10&&a%1000/100==c/10&&a%100/10==b%10&&a%10==b/10)
		return 1;
	return 0;
}
int judge2(int a,int b,int c)
{
	if(a/1000==a%100/10&&a%100/10==b%10&&b%10==c%10&&c%10!=c/10&&c/10==b/10&&b/10==a%10&&a%10==a%1000/100)
		return 1;
	return 0;
}
int main()
{
	int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
	string s;
	cin>>s;
	int a,b,c,a1,b1,c1,d;
	a=(s[0]-'0')*1000+(s[1]-'0')*100+(s[2]-'0')*10+(s[3]-'0');
	b=(s[4]-'0')*10+(s[5]-'0');
	c=(s[6]-'0')*10+(s[7]-'0');
	a1=a,b1=b,c1=c;
	while(1)
	{
		d=day[b];
		if(b==2)
			d+=judge(a);
		if(c<d)
			c++;
		else
		{
			if(b<12)
			{
				b++;
				c=1;
			}
			else
			{
				a++;
				b=1;
				c=1;
			}
		}
		if(judge1(a,b,c)==1)
			break;
	}
	printf("%04d%02d%02d\n",a,b,c);
	a=a1,b=b1,c=c1;
	while(1)
	{
		d=day[b];
		if(b==2)
			d+=judge(a);
		if(c<d)
			c++;
		else
		{
			if(b<12)
			{
				b++;
				c=1;
			}
			else
			{
				a++;
				b=1;
				c=1;
			}
		}
		if(judge1(a,b,c)==1&&judge2(a,b,c)==1)
			break;
	}
	printf("%04d%02d%02d\n",a,b,c);
	return 0;
}

 

H:子串分值和

思路:当时好像是两重循环暴力的,记不太清了,如果是这样肯定没有得全分。

这道题的代码很短,也很考验思维。

采取一种不常规的思维,不去枚举每一个子串,然后计算不相同的字母数;而是计算每个字母作为一个种类,在不同的子串中被加的次数。被加的次数就是:(这个字母的位置-上次它出现的位置)*(这个字母的位置距离串尾的距离)。自行枚举进行理解。

一开始的位置都初始化为-1,表示还没出现过。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
string s;
int book[30];
int main()
{
	memset(book,-1,sizeof(book));
	string s;
	cin>>s;
	int n=s.length(),i,ans=0;
	for(i=0;i<n;i++)
	{
		ans+=(i-book[s[i]-'a'])*(n-i);
		book[s[i]-'a']=i;
	}
	cout<<ans<<endl;
	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值