蓝桥杯2020初赛B 题解 | JorbanS

文章包含多个蓝桥杯2020初赛的编程题目,涉及数学和算法,如门牌制作(字符计数)、既约分数(最大公约数)、蛇形填数(数学规律)、七段码(并查集)、跑步锻炼(日期计算)、回文日期(日期逻辑)、字串排序、成绩统计(数据处理)和子串分值和(字符串处理)。每个题目都提供了C++代码实现来解决问题。
摘要由CSDN通过智能技术生成

[蓝桥杯2020初赛] 门牌制作

Tag 数学

题意 12020 一共有多少字符 2

#include<iostream>
using namespace std;
int ans;

int main(){
	for(int i=1;i<=2020;i++){
		int t=i;
		while(t){
			if(t%10==2)ans++;
			t/=10;
		}
	}
	cout<<ans<<endl;
	return 0;
}

[蓝桥杯2020初赛] 既约分数

Tag gcd

题意 一个分数的分子和分母的最大公约数是 1,这个分数称为既约分数,求 12020 有多少既约分数

#include<iostream>
using namespace std;
int ans;

int gcd(int a,int b){
	return b?gcd(b,a%b):a;
}

int main(){
	for(int i=1;i<=2020;i++)
		for(int j=i+1;j<=2020;j++)
			if(gcd(i,j)==1)ans++;
	cout<<ans*2+1<<endl; // 1/1 特判
	return 0;
}

[ 蓝桥杯2020初赛] 蛇形填数

Tag 数学

1	2	6	7	15	...
4	5	8	14	...
4	9	13	...
10	12	...
11	...
...

题意 求第 2020 列的数

#include<iostream>
using namespace std;

int main(){
	cout<<38*39/2+20<<endl;
	return 0;
}

[蓝桥杯2020初赛] 七段码

Tag 并查集

img

题意 有多少种连成一片的表达字符的方案(只亮 b 和 只亮 c 算一种)。

每条边代表的代号
 1
6 2
 7
5 3
 4
#include<iostream>
#include<cstring>
#define endl '\n'
using namespace std;
const int N=8;
int g[N][N];
int p[N];
bool st[N];

void add(int a,int b){
	g[a][b]=g[b][a]=1;
}

int find(int x){
	if(x!=p[x])p[x]=find(p[x]);
	return p[x];
}
void init(){
	add(1,2),add(1,6);
	add(2,7),add(6,7);
	add(2,3),add(5,6);
	add(5,7),add(3,7);
	add(3,4),add(4,5);
}
int main(){
	init();
	int ans=0;
	for(int i=1;i<1<<7;i++){
		memset(st,0,sizeof st);
		for(int j=1;j<=7;j++)p[j]=j;
		
		for(int j=0;j<7;j++)
			if((i>>j)&1)st[j+1]=1;
		
		for(int j=1;j<=7;j++)
			for(int k=1;k<=7;k++)
				if(g[j][k]&&st[j]&&st[k]){
					int pj=find(j);
					int pk=find(k);
					if(pj!=pk)p[pj]=pk;
				}
		
		int cnt=0;
		for(int j=1;j<=7;j++)
			if(st[j]&&p[j]==j)
				cnt++; // 同为一个祖宗
		if(cnt==1)ans++;
	}
	cout<<ans<<endl;
	return 0;
}

[ 蓝桥杯2020初赛] 跑步锻炼

Tag 数学

题意 小蓝跑步,每天跑 1km,若是每月初或每周一跑 2km,问从 2000.1.1 周六2020.10.1 周四 一共跑了多少千米(含两端点)

#include<iostream>
using namespace std;
const int M[2][12]={
	{31,28,31,30,31,30,31,31,30,31,30,31},
	{31,29,31,30,31,30,31,31,30,31,30,31}
};
bool flag=1;
int ans;

bool isPrime(int x){
	return x%4==0&&x%100||x%400==0;
}

int main(){
	int year=2000,month=0,day=0,week=5;
	while(!(year==2020&&month==9&&day==1)){
		if(day==0||week==0)ans++;
		day++,ans++,week++;
		week%=7;
		if(day==M[flag][month]){
			day=0;
			month++;
			if(month==12){
				month=0;
				year++;
				flag=isPrime(year);
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}

[蓝桥杯2020初赛] 回文日期

Tag 数学

题意 n 个日期格式为 YYYYMMDD,分别输出给定日期后的第一个回文日期和第一个 ABABBABA 格式的日期

#include<iostream>
#define endl '\n'
using namespace std;

const int month[2][12]={
	{31,28,31,30,31,30,31,31,30,31,30,31},
	{31,29,31,30,31,30,31,31,30,31,30,31}
};
bool isPrime(int x){
	return x%4==0&&x%100||x%400==0;
}
bool check(int Y,int M,int D){
	return M>0&&M<=12&&D>0&&D<=month[isPrime(Y)][M-1];
}

void solveA(int x,int y){
	while(1){
		int t=y;
		int Y=0;
		while(t){
			Y=Y*10+t%10;
			t/=10;
		}
		int M=Y/100,D=Y%100;
		int ans=y*10000+M*100+D;
		if(ans>x&&check(Y,M,D)){
			cout<<ans<<endl;
			return;
		}
		y++;
		if(y%10==2)y+=8;
	}

}

void solveB(int x,int y){
	while(1){
		int t=y;
		int tr=t/10+t%10*10;
		int res=t*1000000+t*10000+tr*100+tr;
		int Y=t*100+t,M=tr,D=tr;
		if(res>x&&check(Y,M,D)){
			cout<<res<<endl;
			return;
		}
		y++;
		if(y%10==2)y+=8;
	}
}

int main(){
	int n;cin>>n;
	while(n--){
		int x;cin>>x;
		solveA(x,x/10000);
		solveB(x,x/1000000);
	}
	return 0;
}

[蓝桥杯2020初赛] 字串排序

题意 求出一个字符串依次按优先级满足以下条件:

  • 通过冒泡排序经过 v 次交换
  • 长度最短
  • 字典序zui’xiao

[蓝桥杯2020初赛] 成绩统计

Tag 数学

题意 给定一个满分为 100 分的整数成绩,[60, 100] 为及格,[85,100] 为优秀,输出四舍五入的整数及格率和优秀率

#include<iostream>
#define endl '\n'
using namespace std;

int main(){
	int n;cin>>n;
	int r=0,R=0;
	for(int i=0;i<n;i++){
		int x;cin>>x;
		if(x>=60)r++;
		if(x>=85)R++;
	}
	cout<<int(1.0*r/n*100+0.5)<<'%'<<endl;
	cout<<int(1.0*R/n*100+0.5)<<'%'<<endl;
	return 0;
}

[蓝桥杯2020初赛] 子串分值和

Tag dp

题意 求由小写字母组成的字符串的所有子字符串中不同字符的个数之和

#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=1e5+2;
int dp[N],indx[26]; // indx[i] 表示前面有多少个 i 字符
string s;
ll res=0;

int main(void){
	cin>>s;
	for(int i=1;i<=s.size();i++){
		int t=s[i-1]-'a';
		dp[i]=dp[i-1]+i-indx[t];
		res+=dp[i];
		indx[t]=i;
	}
	cout<<res<<endl;
	return 0;
}

[蓝桥杯2020初赛] 平面切分

Tag 数学

题意 n 条直线,求一共将平面切成了几个部分

#include<iostream>
#include<set>
#define mp make_pair
using namespace std;
set<pair<int,int>> line;
int res=1;

int search(int a,int b){ // 分区数 = 直线数 + 每次新增直线与已存在直线的交点 + 1
	set<pair<double,double>> point;
	for(auto i=line.begin();i!=line.end();i++){
		int A=(*i).first,B=(*i).second;
		if(a==A)continue;
		double x=(b-B)*1.0/(A-a);
		double y=a*x+b;
		int old=point.size();
		point.insert(mp(x,y));
	}
	return point.size();
}
  
int main(void){
	int n;cin>>n;
	while(n--){
		int a,b;cin>>a>>b;
		int l=line.size();
		line.insert(mp(a,b));
		if(l==line.size()||!l)continue;
		res+=search(a,b);
	}
	cout<<res+line.size()<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JorbanS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值