2022蓝桥杯c语言B组编程题题解

本文详细分析了多项算法竞赛中的解题策略,包括C题的刷题统计方法,D题的修剪灌木问题,E题的X进制减法规则,F题的子矩阵统计,G题的积木画动态规划,H题的扫雷策略(未给出),I题的李白打酒加强版的动态规划解决方案,J题的砍竹子问题的优先队列模拟。文章深入探讨了解题思路和优化技巧,对于提升算法竞赛能力具有指导意义。
摘要由CSDN通过智能技术生成

C:刷题统计

先把整周的除掉,剩下看到一周的星期几

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define mod 1000000007
using namespace std; 
int n,m,k,ans;
int a,b;
void solve(){
	cin>>n>>a>>b;
	ans=n/(5*a+2*b);
	n%=(5*a+2*b);
	for(int i=1;i<=5;i++){
		if(n>0) {n-=a;ans++;}
	}
	if(n>0){n-=b;ans++;}
	if(n>0){n-=b;ans++;}
	cout<<ans;
}
signed main(){
	int _=1;
	//cin>>_;
	while(_--)
		solve();
}

D:修剪灌木

对每个 i i i,可以知道答案为 2 ∗ m a x ( n − i , i − 1 ) 2*max(n-i,i-1) 2maxni,i1,代码略。

E:X 进制减法

考虑到每点权值是其低位进制的后缀积,而又因为 A > B A>B A>B所以只需要尽可能地使各位上进制小即可,直接 m a x ( 2 , a [ i ] + 1 , b [ i ] + 1 ) max({2,a[i]+1,b[i]+1}) max(2,a[i]+1,b[i]+1)即可(max套max写法是赛场上担心编译不通过。

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define mod 1000000007
using namespace std; 
int n,m,k,ans;
int a[200005],b[200005],c[200005];
void solve(){
	cin>>k>>n;ans=0;
	for(int i=1;i<=n;i++){cin>>a[i];}
	cin>>m;
	for(int i=n-m+1;i<=n;i++){cin>>b[i];}
	for(int i=1;i<=n;i++){c[i]=max(1ll,max(a[i],b[i]))+1;}
	int res=1;
	for(int i=n;i;i--){
		ans=(ans+mod+res*(a[i]-b[i])%mod)%mod;
		res=res*c[i]%mod;
	}
	cout<<ans;
}
signed main(){
	int _=1;
	//cin>>_;
	while(_--)
		solve();
}

F: 统计子矩阵

解法一:枚举左右边界,上下边界通过双指针确定,复杂度 O ( N 3 ) O(N^3) O(N3)

解法二(我赛时的写法):首先考虑 n 4 n^4 n4做法,即枚举矩形的一个对角线,令对角线坐标为 ( x i , y i ) ( x j , y j ) 且 x j < x i , y j < y i (x_i,y_i)(x_j,y_j) 且x_j<x_i,y_j<y_i xi,yi(xj,yj)xj<xi,yj<yi容易发现当 ( x i , y i ) (x_i,y_i) xi,yi确定时,随着 y j y_j yj的上升满足条件最小的 x i x_i xi下降,这里可用双指针维护。

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define mod 1000000007
using namespace std; 
int n,m,k,ans,qaq;
int a[505][505],sum[505][505];
int qpow(int x,int y,int res=1){
	for(;y;y>>=1,(x*=x)%=mod) if(y&1) (res*=x)%=mod;
	return res;
}
void solve(){
	ans=0;
	cin>>n>>m>>qaq;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
			sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			for(int k=1,t=j;k<=i;k++){
				while(t&&sum[i][j]-sum[k-1][j]-sum[i][t-1]+sum[k-1][t-1]<=qaq){
					t--;
				}
				ans+=j-t;
				//cout<<i<<" "<<j<<" "<<k<<" "<<t<<" "<<ans<<endl;
			}
		}
	}
	cout<<ans;
	
}
signed main(){
	int _=1;
	//cin>>_;
	while(_--)
		solve();
}

G: 积木画

一个挺基础的dp,大概意思是 d p [ i ] [ 0 ] dp[i][0] dp[i][0]表示恰好构成一个 2 ∗ i 2*i 2i的矩形,而 d p [ i ] [ 1 ] dp[i][1] dp[i][1]表示离构成一个 2 ∗ i 2*i 2i的矩形还差一格。模拟一下容易得到以下代码中式子。

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define mod 1000000007
using namespace std; 
int n,m,k,ans,qaq;
int dp[10000006][2]; 
void solve(){
	cin>>n;
	dp[1][0]=1,dp[2][0]=2;
	dp[2][1]=2;
	for(int i=3;i<=n;i++){
		dp[i][0]=(dp[i-1][1]+dp[i-1][0]+dp[i-2][0])%mod;
		dp[i][1]=(dp[i-1][1]+dp[i-2][0]*2)%mod;
	}
	cout<<dp[n][0]<<endl;
}
signed main(){
	int _=1;
	cin>>_;
	while(_--)
		solve();
}

H:扫雷

这题赛时读假了写的代码错的,以后再补吧。

I: 李白打酒加强版

又是一个dp, d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]表示经过i个酒店和j朵花剩k的酒的方案数,在每一点可以选择进酒店或者碰到花,直接三重循环即可。
最后输出 d p [ n ] [ m ] [ 0 ] dp[n][m][0] dp[n][m][0]即可

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define mod 1000000007
using namespace std; 
int n,m,k,ans,qaq;
int dp[106][105][105]; 
void solve(){
	cin>>n>>m;
	dp[0][0][2]=1;
	for(int i=0;i<=n;i++){
		for(int j=0;j<=m;j++){
			for(int k=1;k<=m;k++){
				if(k*2<=m)(dp[i+1][j][k*2]+=dp[i][j][k])%=mod;
				(dp[i][j+1][k-1]+=dp[i][j][k])%=mod;
			}
		}
	}
	cout<<dp[n][m][0];
}
signed main(){
	int _=1;
	//cin>>_;
	while(_--)
		solve();
}

J: 砍竹子

首先容易发现同一个点至多开6次根号。
其次容易发现每次砍当前最高点一定不会比其余情况更劣,所以使用优先队列模拟即可。
开根号要自己重新手写,不然会炸精度,赛时代码没写不知道烂多少。

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define mod 1000000007
using namespace std; 
int n,m,k,ans,qaq;
int a[200005];
struct node{
	int x,l,r;
	bool operator <(const node &t) const {
		return x<t.x||x==t.x&&l>t.l; 
	}
};
priority_queue<node>q;
void solve(){
	ans=0;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		node t={a[i],i,i};
		if(a[i]!=1)q.push(t);
	}
	while(!q.empty()){
		node u=q.top();
		q.pop();
		while(!q.empty()){
			node v=q.top();
			if(u.x==v.x&&v.l==u.r+1){
				u.r=v.r;
				q.pop();
			}
			else{
				break;
			}
		}
		ans++;
		u.x=sqrt(u.x/2+1);
		if(u.x!=1){
			q.push(u);
		}
	}
	cout<<ans;
	
}
signed main(){
	int _=1;
	//cin>>_;
	while(_--)
		solve();
}
蓝桥杯是一个国内著名的计算机比赛,为了帮助参赛者更好地准备和了解比赛的题型,委会会公布历年的真题并提供相应的题解。 首先,我们需要了解蓝桥杯是一个综合性的计算机比赛,测试的对象包括计算机基础知识、编程能力以及解决实际问题的能力。 在历年的真题中,参赛者将面临不同类型的题目,包括算法设计与优化问题、数据结构与算法问题、编程题等。其中针对Python B的题目主要考察的是对Python语言的掌握和应用能力。 题目解答一般会包含以下几个方面的内容: 1. 题目分析与理解:读取题目,理解题目的要求和限制条件。通过仔细分析题目,确定题目的输入与输出,以及问题的核心。 2. 设计解决方案:根据题目要求和限制条件,设计一个合适的解决方案。可以使用合适的算法和数据结构来解决问题,并做出相应的性能优化。 3. 编写代码实现:根据设计的方案编写相应的代码实现。需要注意的是,Python语言有其独特的语法和特性,掌握好这些特性可以更好地完成编程任务。 4. 调试与测试:编写完代码后,需要进行调试和测试。通过运行样例输入和输出,检查代码是否符合题目要求,并且没有逻辑上的错误。 5. 总结与优化:在完成题目解答后,可以进行总结和优化。包括分析算法复杂度、代码风格和可读性等方面,以便在比赛中更好地表现。 在准备蓝桥杯时,可以通过阅读历年的真题和题解来了解比赛的难度和类型,针对性地进行练习和提高。同时也可以参加相关的培训班和讨论活动,与其他参赛者交流经验和技巧。 总而言之,历年蓝桥杯真题的解答对于提高自己的编程能力和应对比赛非常有帮助。通过认真分析和实践,可以更好地理解并掌握Python编程,并在比赛中取得更好的成绩。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值