蓝桥杯校内模拟赛
填空题
填空题比较简单,只需要在空格中填写整数答案即可:
- 在计算机存储中,15.125GB是多少MB?
解题思路: 1GB=1024MB,打开系统计算器计算即可
答案: 15488 - 在1至2019中,有多少个数的数位中包含数字9?
解题思路: 需要注意如果一个数字中包含多个9也只计一个,写一个循环不停取余判断即可
答案: 544 - 1200000有多少个约数?
解题思路: 直接暴力写循环一个一个判断计数即可
答案: 96 - 一棵包含有2019个结点的树,最多包含多少个叶结点?
解题思路: 题目并未说明是二叉树,所以最多可以只有一个根节点,其余全为叶节点
答案: 2018
编程题
-
问题描述:
一个正整数如果任何一个数位不大于右边相邻的数位,则称为一个数位递增的数,例如1135是一个数位递增的数,而1024不是一个数位递增的数。给定正整数 n,请问在整数 1 至 n 中有多少个数位递增的数?输入格式:输入的第一行包含一个整数 n。
输出格式:输出一行包含一个整数,表示答案。
样例输入:
30
样例输出:26
评测用例规模与约定:对于 40% 的评测用例,1 <= n <= 1000。对于 80% 的评测用例,1 <= n <= 100000。对于所有评测用例,1 <= n <= 1000000。
解题思路:
这道题只需要暴力枚举每一个数,再判断这个数字是不是数位递增的数,写个循环不断取余进行每一位每一位的比较判断即可
答案:#include<iostream> using namespace std; int main(){ int number;cin>>number;int times=0; for(int i=1;i<=number;i++){ if(i<10){//个位数成立 times++; } else{ int a=i%10;int b=i/10;int judge=0; while(b>0){ if(a<b%10){ //不成立的情况 judge=1;break; } else{ a=b%10;b=b/10; } } if(judge==0){ times++; } } } cout<<times<<endl; return 0; }
-
问题描述:
问题描述:在数列 a[1], a[2], …, a[n] 中,如果对于下标 i, j, k 满足 0<i<j<k<n+1 且 a[i]<a[j]<a[k],则称 a[i], a[j], a[k] 为一组递增三元组,a[j]为递增三元组的中心。给定一个数列,请问数列中有多少个元素可能是递增三元组的中心。输入格式:输入的第一行包含一个整数 n。第二行包含 n 个整数 a[1], a[2], …, a[n],相邻的整数间用空格分隔,表示给定的数列。
输出格式:输出一行包含一个整数,表示答案。
样例输入:5
1 2 5 3 5
样例输出:2
样例说明:a[2] 和 a[4] 可能是三元组的中心。评测用例规模与约定:对于 50% 的评测用例,2 <= n <= 100,0 <= 数列中的数 <= 1000。对于所有评测用例,2 <= n <= 1000,0 <= 数列中的数 <= 10000。
解题思路:
利用一个vector存储数据,我们写个循环遍历除去首尾的数字,因为首尾不可能成为三元组中心,我的想法是,循环到一个元素,将这个元素的前面所有元素升序排序,将这个元素的后面所有元素升序排序,然后判断该元素是否大于前面的最小值且小于后面的最大值,如果满足则计数加一,最后输出即可,这里选用vector主要是个人习惯,采取数组也是一样的
答案:#include<iostream> using namespace std; #include<vector> #include<algorithm> int main(){ int n;cin>>n; vector<int> arr; for(int i=0;i<n;i++){ int now;cin>>now; arr.push_back(now); } int times=0; vector<int> now; now.assign(arr.begin(),arr.end()); for(int i=1;i<arr.size()-1;i++){ arr.assign(now.begin(),now.end()); sort(arr.begin(),arr.begin()+i-1); sort(arr.begin()+i+1,arr.end()); if(arr[i]>arr[0]&&arr[i]<arr[i+1]){ times++; } } cout<<times<<endl; return 0; }
-
问题描述:
小明要组织一台晚会,总共准备了 n 个节目。然后晚会的时间有限,他只能最终选择其中的 m 个节目。这 n 个节目是按照小明设想的顺序给定的,顺序不能改变。小明发现,观众对于晚上的喜欢程度与前几个节目的好看程度有非常大的关系,他希望选出的第一个节目尽可能好看,在此前提下希望第二个节目尽可能好看,依次类推。小明给每个节目定义了一个好看值,请你帮助小明选择出 m 个节目,满足他的要求。输入格式:输入的第一行包含两个整数 n, m ,表示节目的数量和要选择的数量。第二行包含 n 个整数,依次为每个节目的好看值。
输出格式:输出一行包含 m 个整数,为选出的节目的好看值。
样例输入:5 3
3 1 2 5 4
样例输出:3 5 4
样例说明:选择了第1, 4, 5个节目。评测用例规模与约定:对于 30% 的评测用例,1 <= n <= 20;对于 60% 的评测用例,1 <= n <= 100;对于所有评测用例,1 <= n <= 100000,0 <= 节目的好看值 <= 100000。
解题思路:
之前校内选拔赛遇到过这道题,当时采用的两个一维数组,一个存储数值一个存储对应的次序,进行排序后按次序输出前m个,但是这个方法说实话有点绕,这次直接采用类,写一个类,属性为数值和次序,然后利用vector来存储类对象,先利用数值属性进行降序排列,再把前m个元素赋值给另外一个vector,再利用次序数据对新的vector进行升序排序,然后输出即可
答案:#include<iostream> using namespace std; #include<vector> #include<algorithm> class see{ private: int value; int time; public: see(int a,int b){ value=a;time=b; } int get_value(){ return value; } int get_time(){ return time; } }; bool compare(see a,see b){ return a.get_value()>b.get_value(); } bool recompare(see a,see b){ return a.get_time()<b.get_time(); } int main(){ int n,m;cin>>n>>m; vector<see> arr; for(int i=0;i<n;i++){ int number;cin>>number; see mysee(number,i); arr.push_back(mysee); } sort(arr.begin(),arr.end(),compare); vector<see> result; for(int i=0;i<m;i++){ result.push_back(arr[i]); } sort(result.begin(),result.end(),recompare); for(int i=0;i<m;i++){ cout<<result[i].get_value()<<" "; } return 0; }
-
问题描述:
小明对类似于 hello 这种单词非常感兴趣,这种单词可以正好分为四段,第一段由一个或多个辅音字母组成,第二段由一个或多个元音字母组成,第三段由一个或多个辅音字母组成,第四段由一个或多个元音字母组成。给定一个单词,请判断这个单词是否也是这种单词,如果是请输出yes,否则请输出no。(元音字母包括 a, e, i, o, u,共五个,其他均为辅音字母。)输入格式:输入一行,包含一个单词,单词中只包含小写英文字母。
输出格式:输出答案,或者为yes,或者为no。
样例输入:
lanqiao
样例输出:yes
样例输入:world
样例输出:no
评测用例规模与约定:对于所有评测用例,单词中的字母个数不超过100。
解题思路:
这道题也很简单,只需要对字符串进行遍历,如果遇到s[i]和s[i+1]两者一个是元音字母一个是辅音字母即可计数加一,再通俗点说,遇到前后不一致的时候就加一,如果遍历结束的计数值不为3(从0开始计数)则表示不符合题意,这里也需要注意,满足条件的字符串第一个字母必须是辅音字母,否则都不用进行判断
答案:#include<iostream> using namespace std; #include<string> int judge(char c){ if(c=='a'||c=='e'||c=='i'||c=='o'||c=='u'){ return 1;//元音字母 } else{ return 0;//辅音字母 } } int main(){ string s;cin>>s; if(judge(s[0])==1){ cout<<"no"<<endl; } else{ int times=0; for(int i=0;i<s.length()-1;i++){ if(judge(s[i])!=judge(s[i+1])){ times++; } } if(times==3){ cout<<"yes"<<endl; } else{ cout<<"no"<<endl; } } return 0; }
-
问题描述:
问题描述:小明想知道,满足以下条件的正整数序列的数量:1. 第一项为 n;2. 第二项不超过 n;3. 从第三项开始,每一项小于前两项的差的绝对值。请计算,对于给定的 n,有多少种满足条件的序列。输入格式:输入一行包含一个整数 n。
输出格式:输出一个整数,表示答案。答案可能很大,请输出答案除以10000的余数。
样例输入:
4
样例输出:7
样例说明:以下是满足条件的序列:
4 1
4 1 1
4 1 2
4 2
4 2 1
4 3
4 4
评测用例规模与约定:对于 20% 的评测用例,1 <= n <= 5;对于 50% 的评测用例,1 <= n <= 10;对于 80% 的评测用例,1 <= n <= 100;对于所有评测用例,1 <= n <= 1000。
解题思路:
这道题就比较灵性了,之前校内选拔赛遇到过一次,那时候第一反应是递归,递归编写难度其实不大,运行发现100算不出来了已经,递归是真的费时间啊,然后实在没办法,手动暴力枚举了前七个数据随便交上去得了,山水有相逢,这次又遇到了,认真对待一波,拿到题的第一反应还是递归求解,利用vector方便递归的操作实现,刷刷几分钟写好,很明显是超时的,可以看到递归过程中,我们其实没有必要把每种情况都列举出来,我们只需要的是结果,也就是到底有几种可能,很明显采用动态规划可以节约很多时间
我之前也没有接触过动态规划,毕竟是个菜鸡,只是随随便便写写题,只会用用数组、字符串瞎解决问题,于是我去了解了下动态规划,最后得出结论,动态规划其实就是遇到这种只需要结果的,并且前后数据之间存在某种关系的问题,尝试写一个递推公式,再寻找初值,循环求解即可
这个题算是这次模拟赛最难的一个题了,动态规划题目通常你需要考虑三个问题:
1、用什么数据结构来表示,一维数组还是二维数组,每一个元素的含义是什么?
2、元素之间的递推关系是什么,也就是递推公式怎么来?
3、初始值应该有哪些?
针对本题,我们递归不能白写,很容易想到要求5的可能次数,我们需要分别把以5 1、5 2、5 3、5 4、5 5开头的所有可能次数相加即可,所以递归程序改为如下:#include<iostream> using namespace std; #include<vector> #include<cmath> #include<iomanip> int times=0; int find(vector<int> a){ int flag=a.size(); if(fabs(a[flag-2]-a[flag-1])<=1){ //结束6 } else{//未结束 for(int i=1;i<fabs(a[flag-2]-a[flag-1]);i++){ vector<int> b;b.assign(a.begin(),a.end()); b.push_back(i); find(b);times++; } } } int main(){ int n=10; int data[n][n]; for(int h1=0;h1<n;h1++){ for(int h2=0;h2<n;h2++){ times=0;vector<int> arr; arr.push_back(h1+1);arr.push_back(h2+1); for(int i=1;i<fabs(h1-h2);i++){ vector<int> b;b.assign(arr.begin(),arr.end()); b.push_back(i); find(b);times++; } data[h1][h2]=times+1; } } for(int i=0;i<=n;i++){ cout<<setw(4)<<i<<" "; } cout<<endl; for(int i=0;i<=n;i++){ cout<<"-----"; } cout<<endl; for(int i=0;i<n;i++){ cout<<setw(4)<<i+1<<"|"; for(int j=0;j<n;j++){ cout<<setw(4)<<data[i][j]<<" "; } cout<<endl; } return 0; }
由此我们可以得到如下结果:
如图,输出结果中的dp[i][j]代表以i j开头的字符串可能的个数,那么dp[i][j]的值怎么递推出来呢,这里直接给出,想要理解也很简单,尝试去求解以10 1开头的字符串可能个数你便会顿悟,递推公式如下:
然后我们随便定好初值,进行循环求解即可,但是我们的循环需要先求解行再求解列,具体可以看看程序,当然最后肯定还是能优化的,但这道题有这个速度应该是没问题了
答案:#include<iostream> using namespace std; #include<cmath> long long dp[1001][1001]; int main(){ dp[1][1]=1;dp[1][2]=1;dp[1][3]=3; dp[2][1]=1;dp[2][2]=1;dp[2][3]=1; dp[3][1]=2;dp[3][2]=1;dp[3][3]=3; int n;cin>>n; for(int i=1;i<=n;i++){ for(int j=1;j<=i;j++){ if(fabs(i-j)<=1){ dp[i][j]=1; } else{ dp[i][j]=1; for(int k=1;k<=fabs(i-j)-1;k++){ dp[i][j]+=dp[j][k]; } } } for(int j=1;j<=i;j++){ if(fabs(i-j)<=1){ dp[j][i]=1; } else{ dp[j][i]=1; for(int k=1;k<=fabs(i-j)-1;k++){ dp[j][i]+=dp[i][k]; } dp[j][i]=dp[j][i]%10000; } } } int result=0; for(int j=1;j<=n;j++){ result+=dp[n][j]; result=result%10000; } cout<<result<<endl; return 0; }
-
问题描述:
小明有一块空地,他将这块空地划分为 n 行 m 列的小块,每行和每列的长度都为 1。小明选了其中的一些小块空地,种上了草,其他小块仍然保持是空地。这些草长得很快,每个月,草都会向外长出一些,如果一个小块种了草,则它将向自己的上、下、左、右四小块空地扩展,这四小块空地都将变为有草的小块。请告诉小明,k 个月后空地上哪些地方有草。输入格式:输入的第一行包含两个整数 n, m。接下来 n 行,每行包含 m 个字母,表示初始的空地状态,字母之间没有空格。如果为小数点,表示为空地,如果字母为 g,表示种了草。接下来包含一个整数 k。
输出格式:输出 n 行,每行包含 m 个字母,表示 k 个月后空地的状态。如果为小数点,表示为空地,如果字母为 g,表示长了草。
样例输入:
4 5
.g…
…
…g…
…
2
样例输出:gggg.
gggg.
ggggg
.ggg.
评测用例规模与约定:对于 30% 的评测用例,2 <= n, m <= 20。对于 70% 的评测用例,2 <= n, m <= 100。对于所有评测用例,2 <= n, m <= 1000,1 <= k <= 1000。
解题思路:
这个题比起上一个题就很简单了,直接模拟就行,但是需要注意的情况是,能够往周围延申的草必须是上一个月存在的草,以及要注意数组下标的问题,下标不该减的时候就别去减了,代码如下:
答案:#include<iostream> using namespace std; #include<vector> #include<string> int main(){ int n,m;cin>>n>>m; vector<int> arr[n]; for(int i=0;i<n;i++){ string s;cin>>s; for(int j=0;j<s.length();j++){ if(s[j]=='.'){ arr[i].push_back(-1); } if(s[j]=='g'){ arr[i].push_back(0); } } } int k;cin>>k; for(int c=1;c<k+1;c++){ for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(arr[i][j]>=0&&arr[i][j]!=c){ if(i-1>=0&&arr[i-1][j]==-1){ arr[i-1][j]=c; } if(i+1<n&&arr[i+1][j]==-1){ arr[i+1][j]=c; } if(j-1>=0&&arr[i][j-1]==-1){ arr[i][j-1]=c; } if(j+1<m&&arr[i][j+1]==-1){ arr[i][j+1]=c; } } } } } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(arr[i][j]>=0){ cout<<"g"; } else{ cout<<"."; } } cout<<endl; } return 0; }
总结
本次模拟赛,是在颓废了整整两个月进行的,疫情的原因还没有返校,导致在家是真的堕落,想准备考研被自己的拖延症一直拖一直拖,对于这个模拟赛,就去年参加蓝桥杯省赛B组的经验来看,这次模拟赛的难度和实际比赛差不多,题目类型也一样,很有认真做做的必要,当然是对于我们这些小菜鸡来说哈哈哈