0
点赞
收藏
分享

微信扫一扫

第十三届蓝桥杯省赛(2022年4月17日)C++中级组题解

上善若水的道 2022-04-21 阅读 130
c++蓝桥杯

目录

前言

一、选择题

1.题目描述

2.参考答案

二、编程题

1.比较大小

题目描述

题目解析

AC代码

2.分成整数

题目描述

题目解析

AC代码1(模拟)

AC代码2(dfs)

3.组合

题目描述

题目解析

AC代码1(数论)

AC代码2(Sylvester定理)

4.最大值

题目描述

题目解析

AC代码1(模拟)

AC代码2(二分查找)

5.农作物

题目描述

题目解析

AC代码

6.面积

题目描述

题目解析

AC代码1

AC代码2

前言

一、选择题

1.题目描述

2.参考答案

二、编程题

1.比较大小

题目描述

题目解析

AC代码

#include<iostream>//调用输入输出流头文件
#include<algorithm>//调用算法头文件
using namespace std;//使用标准名字空间
int main(){//主函数开始
	int m,n;//定义整数类型变量m,n
	cin>>m>>n;//输入m,n的值
	cout<<max(m,n);//输出m,n的最大值
    return 0;//主函数结束,返回0
}

2.分成整数

题目描述

题目解析

AC代码1(模拟)

#include<iostream>//调用输入输出流头文件
using namespace std;//使用标准名字空间
bool n37(int n){//子函数,用来判断参数是否含有数字3或7 
	while(n){
		if(n%10==3 or n%10==7) return 1;//如果个位为3或7,返回1 
		n/=10;//删除个位 
	}
	return 0;//如果各位都没有3或7,返回0 
}
int main(){//主函数开始
	int n,cnt=0;//定义整数类型变量n,cnt并初始化赋值为0
	cin>>n;//输入n的值
	for(int i=1;i<=n/3-1;i++){//i为三数中最小,至多为n/3-1 
		if(n37(i)) continue;//如果i含有3或7,跳出本次循环,枚举下一个i 
		for(int j=i+1;j<=n/2;j++){//j为三数中第二小,至多为n/2,保证大于i 
			if(n37(j)) continue;//如果j含有3或7,跳出本次循环,枚举下一个j
			if(n37(n-i-j)) continue;//如果n-i-j含有3或7,跳出本次循环,枚举下一个j
			if(n-i-j>j) cnt++;//走到这一步,则三个正整数一定都不含3或7,只需保证n-i-j>j,则拆分符合条件 
		}
	}
	cout<<cnt;//输出cnt的值
    return 0;//主函数结束,返回0
}

AC代码2(dfs)

#include<iostream>//调用输入输出流头文件
using namespace std;//使用标准名字空间
int cnt;//定义整数类型变量cnt
bool ex_37(int n){//判断37; 
	while(n){
		if(n%10==3 || n%10==7) return 0;//若n包含3或7, 返回 0
		n/=10;//查看下一位
	}
	return 1;//否则返回 1 
}
void dfs(int n,int k,int a){//将 n拆成 k份, 至少拆 a 
	if(k==1){ 	//已拆完 
		if(n>=a) cnt+=ex_37(n);//能拆时,判断n是否含有37
		return;//返回
	}
	for(int i=a;i*k<=n;i++) //继续拆 
		if(ex_37(i))//如果没有37
			dfs(n-i,k-1,i+1);//递归
}
int main(){//主函数开始
	int n;//定义整数类型变量
	cin>>n;//输入n的值
	dfs(n,3,1);//深搜
	cout<<cnt<<endl;//输出cnt
	return 0;//主函数结束,返回0
}

3.组合

题目描述

题目解析

AC代码1(数论)

#include<iostream>//调用输入输出流头文件
using namespace std;//使用标准名字空间
int main(){//主函数开始
	int n,m;//定义整数类型变量n,m
	cin>>n>>m;//输入n,m的值
	int i=m*n-1;//i从m*n-1开始向下枚举 
	while(1){//装死循环
		int j=i,flag=1;//用j代替i来枚举,因为过程中需要j不停自减,立个flag 
		while(j>=0){//当j还为正整数时,继续检查j 
			if(j%n==0) {flag=0;break;}//如果j是n的倍数,则一定能表示出来,flag倒下,跳出循环 
			j-=m;//如果j不是n的倍数,减掉一个m后继续检查 
		}
		if(flag==1) break;//如果flag还在,说明j一直不能被表示,跳出循环 
		i--;//如果flag倒了,则说明j能被表示,i--,检查下一个数,继续循环 
	}
	cout<<i;//输出i的值
    return 0;
}

AC代码2(Sylvester定理)

#include<iostream>//调用输入输出流头文件
using namespace std;//使用标准名字空间
int main(){//主函数开始
	int n,m;//定义整数类型变量n,m
	cin>>n>>m;//输入n,m的值
	cout<<n*m-n-m<<endl;//输出n*m-n-m的值并换行
	return 0;//主函数结束,返回0
}

4.最大值

题目描述

题目解析

AC代码1(模拟)

#include<iostream>//调用输入输出流头文件
#include<algorithm>//调用算法头文件
using namespace std;//使用标准名字空间
int main(){//主函数开始
	int n,k;int a[500],b[500]; //数组a,b分别用来存储长和宽 
	cin>>n;//输入n的值
	for(int i=0;i<n;i++)//for循环,计数器i从0自增到n-1,共循环n次
		cin>>a[i]>>b[i];//输入n个长方形的长和宽 
	cin>>k;//输入k的值
	int big=max(*max_element(a,a+n),*max_element(b,b+n));//找到所有长宽中的最大值 
	while(1){//装死循环
		int sum=0;//sum用来存储所有正方形中能剪出的正方形个数 
		for(int i=0;i<n;i++)
			sum+=(a[i]/big)*(b[i]/big);//对于每一个要剪出的正方形,每张纸能剪出的个数即为该算式 
		if(sum>=k) break;//如果正方形个数够了,跳出循环 
		big--;//big自减1
	}
	cout<<big;//输出此时的边长 
    return 0;//主函数结束,返回0
}

AC代码2(二分查找)

#include<iostream>//调用输入输出流头文件
using namespace std;//使用标准名字空间
int n,k,w[509],h[509];//定义整数类型n,k,w[509],h[509]
bool check(int a){//判断: 切边长为 a的小正方形能否凑够 k个 
	int cnt=0;//定义计数器cnt
	for(int i=0;i<n;++i)//for循环,计数器i从0自增到n-1,共循环n次
		cnt+=(w[i]/a)*(h[i]/a);	//就硬切, 然后硬加 
	return (cnt>=k); //返回cnt是否大于k
}
int main(){//主函数开始
	cin>>n;//输入n的值
	for(int i=0;i<n;++i)//for循环,计数器i从0自增到n-1,共循环n次
		cin>>w[i]>>h[i];//w和 h的顺序其实也无所谓, 摊手 
	cin>>k;//输入k的值
	int L=1, R=*max_element(w,w+n)+1;//随便搞个上下限, 无脑二分:
	while(L+1<R){//当L+1小于R
		int mid=(L+R)/2;//往中间猜 
		if(check(mid)) L=mid;//猜对-->边长小了-->提高下限 
		else R=mid;//猜错-->边长大了-->降低上限
	}
	cout<<L<<endl;//输出L的值
	return 0;//主函数结束,返回0
}

5.农作物

题目描述

题目解析

AC代码

#include<iostream>//调用输入输出流头文件
using namespace std;//使用标准名字空间
char farm[509][509];//土地 farm: R代表农田, X代表杂草  
int sign[509][509];//状态 sign: 0代表未知, 1代表已知农田, -1代表已知杂草
void dfs(int i,int j){//记录所有相邻的农田  
	if(sign[i][j]) return;//搜过了 
	if(farm[i][j]=='X')//如果有杂草
		sign[i][j]=-1;//记住杂草 
	else{//否则
		sign[i][j]=1;//记住农田, 看看周围有无农田 
		dfs(i-1,j);//上
		dfs(i+1,j);//下
		dfs(i,j-1);//左
		dfs(i,j+1);//右
	}
}
int main() {//主函数结束,返回0
	int n,m,cnt;//定义整数类型变量n,m,cnt
	cin>>n>>m;//输入n,m的值
	for(int i=1;i<=n;++i)//for循环,计数器i从1自增到n,共循环n次
		for(int j=1;j<=m;++j)//for循环,计数器j从1自增到m,共循环m次
			cin>>farm[i][j];//缓冲带: 用杂草把农田围起来 
	for(int i=0;i<=n+1;++i)//for循环,计数器i从0自增到n+1,共循环n+2次
		sign[i][0]=sign[i][m+1]=-1;//记录
	for(int j=0;j<=m+1;++j)//for循环,计数器j从0自增到m+1,共循环m+2次
		sign[0][j]=sign[n+1][j]=-1;//记录
	//开搜	
	for(int i=1;i<=n;++i)//for循环,计数器i从1自增到n,共循环n次
		for(int j=1;j<=m;++j)//for循环,计数器j从1自增到m,共循环m次
			if(!sign[i][j] && farm[i][j]=='R'){//发现了未被记录过的农田 
				cnt++;//cnt自增1
				dfs(i,j);//以此为起点开始搜索 
			}
	cout<<cnt<<endl;//输出cnt的值
	return 0;//主函数结束,返回0
}

6.面积

题目描述

题目解析

AC代码1

#include<iostream>//调用输入输出流头文件
using namespace std;//使用标准名字空间
bool xy[110][110];//二维数组,用来组成点阵信息
int ans;//定义整数类型变量ans
int main(){//主函数开始
	int n;//定义整数类型变量
	cin>>n;//输入n的值
	int x1,y1,x2,y2;//定义整数类型变量x1,x2,y1,y2
	for(int i=0;i<n;i++){
		cin>>x1>>y1>>x2>>y2;//循环输入每一个矩形的坐标信息
		for(int j=y1+1;j<=y2;j++)  
			for(int k=x1+1;k<=x2;k++)
				xy[j][k]=1;//记录每个矩形点阵信息
	}	
	for(int j=1;j<=109;j++){//for循环,计数器i从1自增到109,共循环109次
		for(int k=1;k<=109;k++)//for循环,计数器k从1自增到109,共循环109次
			if(xy[j][k]) ans++;//累积数组中为真的个数,即为面积 
	}
	cout<<ans;//输出ans
	return 0;//主函数结束,返回0
}

AC代码2

#include<iostream>//调用输入输出流头文件
using namespace std;//使用标准名字空间
int a[509][509],n;
int main(){//主函数开始
	int x1,y1,x2,y2;//定义整数类型x1,x2,y1,y2
    cin>>n;//输入n的值
    for(int i=0;i<n;i++){//for循环,计数器i从0自增到n-1,共循环n次
        cin>>x1>>y1>>x2>>y2;//输入x1,y1,x2,y2
        a[x1+1][y1+1]++;//a[x1+1][y1+1]自增1
        a[x2+1][y1+1]--;//a[x2+1][y1+1]自减1
        a[x1+1][y2+1]--;//a[x1+1][y2+1]自减1
        a[x2+1][y2+1]++;//a[x2+1][y2+1]自增1
    }
	long long sum=0;//定义长整数类型变量sum并初始化赋值为0
	for(int i=1;i<=20;++i)//for循环,计数器i从1自增到20,共循环20次
		for(int j=1;j<=20;++j){//for循环,计数器j从1自增到20,共循环20次
			a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];//a[i][j]自增a[i-1][j]+a[i][j-1]-a[i-1][j-1]
			//此时 a[i][j]里记录的就是每个点被覆盖的次数 
			if(a[i][j]>0) sum++;//如果a[i][j]>0,sum自增1
		}		
	cout<<sum<<endl;//输出sum的值
	return 0;//主函数结束,返回0
}
举报

相关推荐

0 条评论