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


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

    1、九进制转十进制

    在这里插入图片描述

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

    2、顺子日期

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

    #include
    
    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    3、刷题统计

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

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

    #include
    #include
    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    4、修建灌木

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

    #include
    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    5、x进制减法

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

    代码示例:

    #include
    #include
    #include
    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    6、统计子矩阵

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

    分析:

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

    #include
    #include
    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    7、积木画

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

    #include 
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    8、扫雷

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

    #include
    #include
    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    9、李白打酒加强版

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    遇到这一种给你n,m个数,然后有一些条件,在这些条件的情况,去求特定答案的解,一般都是最多/最少的数量。
    这种题都需要使用递推的思想,因为中间的过程肯定有很多个我们直接·去判断寻找那肯定是不可能的,所以我们要总结规律,暴力的解法就是使用搜索层层递进,如果是答案的话那么就返回,也可以剪枝提高效率,或者找到规律总结状态转移方程使用动态规划。

    #include
    #include 
    #define ll long long
    using namespace std;
    const int p = 1e9+7,N = 105;
    ll dp[N][N][N];
    //表示当前酒的数量,遇到店的数量,遇到花的数量 
    ll dfs(int now,int n,int m){
    	if(n<0||m<0||now<0)return 0;
    	if(m<now)return 0;//因为遇到花要喝酒 
    	if(m==1)return now==1&&n==0;// 最后遇到花的情况 
    	if(dp[now][n][m]!=-1)return dp[now][n][m];// 记忆化搜索 
    	dp[now][n][m]=(dfs(now*2,n-1,m)%p+dfs(now-1,n,m-1)%p)%p;
    	return dp[now][n][m];
    }
    int main(){
    	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    	int n,m;cin>>n>>m;
    	memset(dp,-1,sizeof(dp));
    	dfs(2,n,m);
    	cout<<dp[2][n][m];
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    10、砍竹子

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

    #include
    using namespace std;
    using ll = long long;
    const int N=2e5+10,M=10;
    ll a[N][M],s[N],ans;
    ll sqr(ll x){//sqrt只适用于int,所以要自己写一个函数
        ll ans=0,l=1,r=1e9;
    	while(l<r){
    		ll mid=(l+r)>>1;
    		if(mid*mid<=x){
    			l=mid+1;
    		}else{
    			r=mid;
    		}
    	}
        return l-1;
    }
    int main()
    {
    	int n;cin>>n;
    	ll x=0;
        for(int i=0;i<n;i++){   
        	int y=0;
            cin>>x;
            while(x>1){
                s[++y]=x;
                x=sqr(x/2+1);
            }
            ans+=y;
            for(int j=0,k=y;k;j++,k--)a[i][j]=s[k];
        }
        // 检查相邻的数是否相等,若相等则操作次数减1
        for(int j=0;j<M;j++)
    		for(int i=1;i<n;i++)
    			if(a[i][j]&&a[i][j]==a[i-1][j])ans--; 
        cout<<ans;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
  • 相关阅读:
    【List-Watch】
    【python学习】AC自动机 高效敏感词过滤与文本匹配:全面掌握pyahocorasick库 (NLP自然语言处理项目实战)
    Python爬虫获取百度图片+重命名+帧差法获取关键帧
    华虹半导体冲刺科创板上市:简称为华虹宏力,拟募资180亿元
    Git信息泄露原理解析及利用总结
    详细步骤讲解matlab代码通过Coder编译为c++并用vs2019调用
    Neurocomputing投稿记录
    Android 安全功能
    Redis数据库的发布与订阅(详细讲解)
    Linux 中 WIFI 和热点的使用
  • 原文地址:https://blog.csdn.net/m0_73337964/article/details/137283506