第十四届蓝桥杯软件类 1 期模拟赛填空题及题解

本文介绍了蓝桥杯软件类竞赛中的三道填空题,涉及调和级数计算、查找字母矩阵中的“山谷”以及使用二维前缀和解决矩阵子区域求和问题。对于这些问题,分别给出了C++代码实现,强调了在时间限制内优化算法的重要性。
摘要由CSDN通过智能技术生成

蓝桥杯还剩仅仅10天,但是本人现在才开始准备啊!!!不过事已至此只好刷一点题练练手感了,系统地去学算法肯定是来不及啦。

题目来源:第十四届蓝桥杯软件类 1 期模拟赛(大学组)填空题3,4,5

填空3:项数

【问题描述】

小蓝特别喜欢调和级数 S(n) = 1/1 + 1/2 + 1/3 + 1/4 +…+ 1/n 。

请问,n 至少为多大时,S(n) > 12 ?

【运行限制】

最大运行时间:1s

最大运行内存: 256M

【解析】

第一题要求调和级数,本来想通分用分子除以分母来计算S(n),但是发现这样会超时,心想填空题不会在精度上做文章吧,那就用double直接算试试,答案就出来了。

#include<iostream>
using namespace std;
int main(){
	double S=0;
	int i=1;
	for(i=1;S<=12.0;i++){
		S+=1.0/i;
	}
	cout<<i-1;
	return 0;
}

填空4:山谷 

【问题描述】

给定一个字母矩阵,如果矩阵中的某个位置不在四条边上,而且该位置上的字母小于其上下左右四个位置的字母,则称为一个山谷。

例如,对于如下矩阵

DDDDD
CADCE
FFFFA

共有两个山谷,位于第二行第二列和第四列。请注意第二行第三列和第三行第五列都不是山谷。

对于如下 30 行 60 列的字母矩阵,请问有多少个山谷?

PHQGHUMEAYLNLFDXFIRCVSCXGGBWKFNQDUXWFNFOZVSRTKJPREPGGXRPNRVY
STMWCYSYYCQPEVIKEFFMZNIMKKASVWSRENZKYCXFXTLSGYPSFADPOOEFXZBC
OEJUVPVABOYGPOEYLFPBNPLJVRVIPYAMYEHWQNQRQPMXUJJLOOVAOWUXWHMS
NCBXCOKSFZKVATXDKNLYJYHFIXJSWNKKUFNUXXZRZBMNMGQOOKETLYHNKOAU
GZQRCDDIUTEIOJWAYYZPVSCMPSAJLFVGUBFAAOVLZYLNTRKDCPWSRTESJWHD
IZCOBZCNFWLQIJTVDWVXHRCBLDVGYLWGBUSBMBORXTLHCSMPXOHGMGNKEUFD
XOTOGBGXPEYANFETCUKEPZSHKLJUGGGEKJDQZJENPEVQGXIEPJSRDZJAZUJL
LCHHBFQMKIMWZOBIWYBXDUUNFSKSRSRTEKMQDCYZJEEUHMSRQCOZIJIPFION
EEDDPSZRNAVYMMTATBDZQSOEMUVNPPPSUACBAZUXMHECTHLEGRPUNKDMBPPW
EQTGJOPARMOWZDQYOXYTJBBHAWDYDCPRJBXPHOOHPKWQYUHRQZHNBNFUVQNQ
QLRZJPXIOGVLIEXDZUZOSRKRUSVOJBRZMWZPOWKJILEFRAAMDIGPNPUUHGXP
QNJWJMWAXXMNSNHHLQQRZUDLTFZOTCJTNZXUGLSDSMZCNOCKVFAJFRMXOTHO
WKBJZWUCWLJFRIMPMYHCHZRIWKBARXBGFCBCEYHJUGIXWTBVTREHBBCPXIFB
XVFBCGKCFQCKCOTZGKUBMJRMBSZTSSHFROEFWSJRXJHGUZYUPZWWEIQURPIX
IQFLDUUVEOOWQCUDHNEFNJHAIMUCZFSKUIDUBURISWTBRECUYKABFCVKDZEZ
TOIDUKUHJZEFCZZZBFKQDPQZIKFOBUCDHTHXDJGKJELRLPAXAMCEROSWITDP
TPCCLIFKELJYTIHRCQAYBNEFXNXVGZEDYYHNGYCDRUDMPHMECKOTRWOSPOFG
HFOZQVLQFXWWKMFXDYYGMDCASZSGOVSODKJGHCWMBMXRMHUYFYQGAJQKCKLZ
NAYXQKQOYZWMYUBZAZCPKHKTKYDZIVCUYPURFMBISGEKYRGZVXDHPOAMVAFY
RARXSVKHTQDIHERSIGBHZJZUJXMMYSPNARAEWKEGJCCVHHRJVBJTSQDJOOTG
PKNFPFYCGFIEOWQRWWWPZSQMETOGEPSPXNVJIUPALYYNMKMNUVKLHSECDWRA
CGFMZKGIPDFODKJMJQWIQPUOQHIMVFVUZWYVIJGFULLKJDUHSJAFBTLKMFQR
MYJFJNHHSSQCTYDTEAMDCJBPRHTNEGYIWXGCJWLGRSMEAEARWTVJSJBAOIOJ
LWHYPNVRUIHOSWKIFYGTYDHACWYHSGEWZMTGONZLTJHGAUHNIHREQGJFWKJS
MTPJHAEFQZAAULDRCHJCCDYRFVVRIVUYEEGFIVDRCYGURQDREDAKUBNFGUPR
OQYLOBCWQXKZMAUSJGMHCMHGDNMPHNQKAMHURKTRFFACLVGRZKKLDACLLTEO
JOMONXRQYJZGINRNNZWACXXAEDRWUDXZRFUSEWJTBOXVYNFHKSTCENAUMNDD
XFDMVZCAUTDCCKXAAYDZSXTTOBBGQNGVVPJGOJOGLMKXGBFCPYPCKQCHBDDZ
WRXBZMQRLXVOBTWHXGINFGFRCCLMZNMJUGWWBSQFCIHUBSJOLLMSQSGHMCPH
ELSOTFLBGSFNPCUZSRUPCHYNVZHCPQUGRIWNIQXDFJPWPXFBLKPNPEELFJMT

【运行限制】

最大运行时间:1s

最大运行内存: 256M

【解析】

 初看第二题有点懵,这啥意思!?

 经过冷静仔细的分析发现只是看上去吓人罢了,题目的意思就是让你找出一个矩阵中满足比他上下左右四个字母都要小的条件的所有字母,可以用字符串数组存储矩阵,然后遍历这个二维字符数组,满足strs[j][z]<strs[j][z-1]&&strs[j][z]<strs[j][z+1]&&strs[j][z]<strs[j-1][z]&&strs[j][z]<strs[j+1][z]即小于上下左右四个字母则结果变量res++。

#include<iostream>
using namespace std;
int main(){
	string strs[30];
	int res=0;
	for(int i=0;i<30;i++){
		cin>>strs[i];
	}
	for(int j=1;j<29;j++){
		for(int z=1;z<59;z++){
			if(strs[j][z]<strs[j][z-1]&&strs[j][z]<strs[j][z+1]&&strs[j][z]<strs[j-1][z]&&strs[j][z]<strs[j+1][z]){
				res++;
			}
		}
	}
	cout<<res;
	return 0;
}

填空5:矩阵拆分

【问题描述】

小蓝有一个 100 行 100列的矩阵,矩阵的左上角为 1。其它每个位置正好比其左边的数大 2,比其上边的数大 1 。

例如,第 1 行第 2 列为 3 ,第 2 行第 2 列 为 4,第 10 行第 20 列为 48。

小蓝想在矩阵中找到一个由连续的若干行、连续的若干列组成的子矩阵,使得其和为 2022,请问这个子矩阵中至少包含多少个元素(即子矩阵的行数和列数的乘积)。

【运行限制】

最大运行时间:1s

最大运行内存: 256M

【解析】

这一题一开始的想法是暴力用四个循环遍历所有子矩阵求解,但是不出意料地超时了,上网一搜了解到二维前缀和算法,是一个基础算法(呜呜呜,都怪没有提前学习算法,现在再去系统地学习算法肯定是来不及辽,只好刷到多少算多少咯)。

首先学习一维前缀和算法,前缀和算法的本质就是就是计算前i个数组元素的和,这样我们计算数组中某一段连续区间的和时就不需要每次都遍历一下数组了,直接用前缀和数组中的和相减即可。比如要计算原数组第i个元素到第j个元素之和,只需要拿前缀和数组s[j](前j个元素之和)- s[i-1](前i-1个元素之和)即a[i]到a[j]的和(假设数组下标从1开始)。

再上升到二维数组中(下标从[1][1]开始,为了避免越位),s[i][j]即求以坐标为[i][j]和[1][1]为顶点所组成矩阵中所有元素之和,这要怎么求呢,这里推荐一个大佬写的文章讲得十分清楚,也解释了为什么前缀和数组和原数组的下标要从1开始-------------传送门

#include <iostream>
using namespace std;
#define n 101
int main()
{
  //表示出矩阵
  int array[n][n];
  for(int i=1;i<n;i++){
    array[i][1]=i;
    for(int j=2;j<n;j++){
      array[i][j]=array[i][j-1]+2;
    }
  }
  //前缀和数组
  int sum[n][n];
  for(int i=1;i<n;i++){
    for(int j=1;j<n;j++){
      sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+array[i][j];
    }
  }
  //遍历所有子矩阵
  int temp;
  int res;
  for(int i=1;i<n;i++){
    for(int j=1;j<n;j++){
      for(int x=i;x<n;x++){
        for(int y=j;y<n;y++){
          temp=sum[x][y]-sum[i-1][y]-sum[x][j-1]+sum[i-1][j-1];
          if(temp==2022){
            res=(x-i+1)*(y-j+1);
          }
          else if(temp>2022){
            break;
          }
        }
      }
    }
  }
  cout<<res;
  return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值