第十三届蓝桥杯大赛软件赛省赛CC++大学B组

时间:2024-04-09 07:19:55

第十三届蓝桥杯大赛软件赛省赛CC++ 大学 B 组

文章目录

  • 第十三届蓝桥杯大赛软件赛省赛CC++ 大学 B 组
    • 1、九进制转十进制
    • 2、顺子日期
    • 3、刷题统计
    • 4、修建灌木
    • 5、x进制减法
    • 6、统计子矩阵
    • 7、积木画
    • 8、扫雷
    • 9、李白打酒加强版
    • 10、砍竹子

1、九进制转十进制

在这里插入图片描述

计算器计算即可。2999+29+2。

2、顺子日期

在这里插入图片描述
简单的枚举一下2022年的日期即可,注意遇到20220123,判断为一个即可。

#include<iostream>

#define ll long long
using namespace std;
int ans=0;
int d[]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 
int main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	for(int i=1;i<=12;i++){
		for(int j=1;j<=d[i];j++){
			int date[]={2,i/10,i%10,j/10,j%10};
			for(int k=0;k<3;k++){
				if(date[k]+1==date[k+1]&&date[k+1]+1==date[k+2]){
					ans++;
					break;
				}
			}
		}
	}
	cout<<ans;
	return 0;
}

3、刷题统计

在这里插入图片描述
分析:

这一题我本来用的是cmath里的ceil函数,但是提交之后我发现只能过掉70%,并没有全部通过。
随后我手写了ceil函数的功能,然后就可以100%通过了。
后来我就发现ceil函数原型是float ceilf (float x); 题意是1e18,肯定就会出现精度问题了,真的要记住这问题了,遇到特大数尽量手心函数,不要用库函数,可能就会出现问题。

#include<iostream>
#include<cmath>
#define ll long long
using namespace std;
ll a,b,n;
int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>a>>b>>n;
	ll x=(5*a+2*b);
	ll y=(n/x);// 坐满了几周,7*y 
	ll z=(n%x);// 还剩的题数 
	if(z<=5*a){
		if(z%a==0){
			z=z/a;
		}else{
			z=z/a+1;
		}
		cout<<7*y+z;
	}else{
		if((z-5*a)%b==0){
			z=(z-5*a)/b;
		}else{
			z=(z-5*a)/b+1;
		}
		cout<<7*y+5+z;
	}
	return 0;
}

4、修建灌木

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这一题直接暴力模拟过程即可,对于案例n=3,我们模拟过程会发现一个规律,那就是在1~n中最高的树是对称的而且最高的树的值都是这两个对称位置步长的2倍。

#include<iostream>
#define ll long long
using namespace std;
int n;
int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>n;
	/*
		n=3
		未剪   修剪后 	位置
		111 -> 011      1
		122 -> 101 		2
			
		212 -> 210		3
		321 -> 301		2
		412 -> 012		1
		123 -> 103 		2
		214 -> 210		3		
		可以看到出现了循环情况,也就说从左向右和从右向左,的最大值是就是步长的2倍 
	*/
	for(int i=1;i<=n;i++){
		cout<<max(i-1,n-i)*2<<"\n";
	}
	return 0;
}

5、x进制减法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
没想到啊,感觉脑袋被踢了。

代码示例:

#include<iostream>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
const ll mod = 1000000007,N = 1e5+10;
ll n,ma,mb,a[N],b[N],p[N];
int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>n;
	// 从高位县向低位输入,避免造成位数不相同 
	cin>>ma;
	for(ll i=ma;i>=1;i--)cin>>a[i];
	cin>>mb;
	for(ll i=mb;i>=1;i--)cin>>b[i];
	/*
		x进制类比一下 十进制 
		比如 123 就是 1*10*10+2*10+3
		那么x进制的:
		每一位的进制:11 5 2
		每一位的数字:10 4 1
		那么这个x进制对应的十进制不就是:10*5*2+4*2+1 
	*/
	// A >= B 	
	// 进制: 11 5 2  
	// 10 4 0  10*5*2+4*2+0=108
	// 1  2 0  1*5*2+2*2+0=14   108-14=94
	// 所以说最小的数位上的进制应该就是a[i]和b[i]这个数位的值+1 
	// 也就是说正好要进位的时候能得到最小值
	// 我们就使用p[i]来储存每个位上应该是什么进制 
	for(ll i=1;i<=ma;i++){
		p[i]=max((ll)2,max(a[i],b[i])+1);
	}
	p[0]=1;
	ll ans=0;
	for(int i=ma;i>=1;i--){ 
		// 为什么需要ans+a[i]+b[i]就能计算这个结果了?
		// 我们可以用两个十进制的数写一下,我们会发现ans其实就是最高位上没减完的数,然后加到下一位上了
		ans=(ans+a[i]-b[i])*p[i-1]%mod;
	}
	cout<<ans;
	return 0;
}

6、统计子矩阵

在这里插入图片描述
在这里插入图片描述

分析:

我直接想到的就是二维前缀和解决这个问题,去拿区间的值和k判断即可。
写的时候运行的结果一直不对,后来才发现是公式记错了,所以说记公式很重要。
区间的形式求值得公式是:res=prefix[x2][y2]-prefix[x2][y1-1]-prefix[x1-1][y2]+prefix[x1-1][y1-1] 。
但是直接暴力解决的话,只能过70%,其它的超时。优化的方法自行搜索。

#include<iostream>
#include<cstring>
#define ll long long
#define pii pair<ll,ll>
using namespace std;
const int N = 5e2+10;
ll n,m,k,mp[N][N],prefix[N][N],ans=0;
int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>n>>m>>k;
	memset(prefix,0,sizeof(prefix));
	memset(mp,0,sizeof(mp));
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){	 
			cin>>mp[i][j];
			prefix[i][j]=prefix[i-1][j]+prefix[i][j-1]+mp[i][j]-prefix[i-1][j-1];
		}
	
	for(int x1=1;x1<=n;x1++){
		for(int y1=1;y1<=m;y1++){
			for(int x2=x1;x2<=n;x2++){
				for(int y2=y1;y2<=m;y2++){
					// s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]
					ll res=prefix[x2][y2]-prefix[x2][y1-1]-prefix[x1-1][y2]+prefix[x1-1][y1-1];
					if(res<=k)ans++;
				}
			} 
		}
	}		
	cout<<ans;
	return 0;
}

7、积木画

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
递推思想。看了也不太懂,可以看看这个博客,讲的很清晰。
请点击:详细题解博客

#include <iostream>
using namespace std;
const int N = 1e7+10, mod = 1e9+7;
using ll = long long;
ll res[N];
int main(){
    int n;
    cin >> n;
    res[0] = 1;
    ll sum = 0;
    for(int i = 1, j = -2 ; i <= n ; ++i, ++j){
        res[i] = res[i-1];
        if(i >= 2) res[i] += res[i-2], res[i] %= mod;
        if(j >= 0) sum += res[j], sum %= mod;
        res[i] += sum << 1, res[i] %= mod;
    }
    cout << res[n];
    return 0;
}

8、扫雷

在这里插入图片描述
在这里插入图片描述
简单的枚举判断一下就行了。

#include<iostream>
#include<cstring>
#define ll long long
using namespace std;
const int N = 105;
int n,m; 
int mp[N][N],ans[N][N];
int dx[]={0,0,1,-1,1,-1,1,-1};
int dy[]={1,-1,0,0,1,-1,-1,1};
bool isnmp(int x,int y){
	return x<0||x>=n||y<0||y>=m;
}
int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>n>>m;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			cin>>mp[i][j];
	memset(ans,'0',sizeof(ans));
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			if(mp[i][j]==1){
				ans[i][j]=9;	
			}else{
				int rs=0;
				for(int k=0;k<8;k++){
					int nx=i+dx[k],ny=j+dy[k];
					if(isnmp(nx,ny))continue;
					if(mp[nx][ny]==1){
						rs++;
					}
				}
				ans[i][j]=rs;
			}
		}
	}	
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++)
			cout<<ans[i][j]<<" ";
		cout<<"\n";
	}
	return 0;
}

9、李白打酒加强版

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入代码片

10、砍竹子

在这里插入图片描述
在这里插入图片描述

在这里插入代码片