第七届蓝桥杯(软件类)省赛C++B组真题题解
题目链接
B组真题
注:其他题目与A组题目相同,题解在我的A组题解中,传送门
题目结构
| 题目 | 类型 | 分值 |
|---|---|---|
| 第一题 | 结果填空 | 3分 |
| 第二题 | 结果填空 | 5分 |
| 第三题 | 结果填空 | 11分 |
| 第四题 | 代码填空 | 9分 |
| 第五题 | 代码填空 | 13分 |
| 第六题 | 结果填空 | 15分 |
| 第七题 | 结果填空 | 19分 |
| 第八题 | 程序设计 | 21分 |
| 第九题 | 程序设计 | 23分 |
| 第十题 | 程序设计 | 31分 |
第一题 煤球数目
-
问题重现
有一堆煤球,堆成三角棱锥形。具体:
第一层放1个,
第二层3个(排列成三角形),
第三层6个(排列成三角形),
第四层10个(排列成三角形),
…
如果一共有100层,共有多少个煤球?请填表示煤球总数目的数字。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。 -
解题思路、
易知 a i − a i − 1 = i a_i-a_{i-1}=i ai−ai−1=i,我们累加即可。
-
代码
/**
* @filename:煤球数目.cbp
* @Author : pursuit
* @Blog:unique_pursuit
* @email: 2825841950@qq.com
* @Date : 2021-03-18-21.28.26
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn=1e5+5;
const int mod=1e9+7;
//易知ai-a(i-1)=i。累加即可。我们认为第0层为0。
//171700
void solve(){
int temp=0,ans=0;
for(int i=1;i<=100;i++){
temp+=i;
ans+=temp;
cout<<temp<<" ";
}
cout<<ans<<endl;
}
int main(){
solve();
return 0;
}
-
答案
171700 171700 171700.
第三题 凑算式
-
问题重现
A + C B + D E F G H I = 10 A+\frac{C}B+\frac{DEF}{GHI}=10 A+BC+GHIDEF=10
这个算式中A~I代表1->9的数字,不同的字母代表不同的数字。
比如:
6 + 8 / 3 + 952 / 714 6+8/3+952/714 6+8/3+952/714 就是一种解法,
5 + 3 / 1 + 972 / 486 5+3/1+972/486 5+3/1+972/486 是另一种解法。这个算式一共有多少种解法?
注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。
-
解题思路
暴力全排列或者 d f s dfs dfs都可以处理,要注意的就是我们怎么处理这个算式,绝对不能直接计算,需要同分再移位,把除号给去掉。
-
代码
/**
* @filename:凑算式.cbp
* @Author : pursuit
* @Blog:unique_pursuit
* @email: 2825841950@qq.com
* @Date : 2021-03-18-21.39.51
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn=1e5+5;
const int mod=1e9+7;
//dfs或暴力全排列。
bool vis[10];//vis[i]表示i是否被选择。
int a[10];//a[1]->a[9]对应ABCDEFGHI。
int ans=0;
void dfs(int step){
//step表示当前正在填第几个数。
if(step==10){
//说明前9个数已经填完了,我们判断。注意不要掉入题目的坑,利用通分之后的式子进行运算。
int temp1=a[7]*100+a[8]*10+a[9],temp2=a[4]*100+a[5]*10+a[6];
if(a[1]*a[3]*temp2+a[2]*temp2+a[3]*temp1==10*a[3]*temp2){
ans++;
}
return;
}
for(int i=1;i<10;i++){
if(!vis[i]){
vis[i]=true;
a[step]=i;
dfs(step+1);
vis[i]=false;
}
}
}
void solve(){
dfs(1);
cout<<ans<<endl;
}
int main(){
solve();
return 0;
}
-
答案
29 29 29.
第五题 抽签
-
问题重现
X星球要派出一个5人组成的观察团前往W星。
其中:
A国最多可以派出4人。
B国最多可以派出2人。
C国最多可以派出2人。
…那么最终派往W星的观察团会有多少种国别的不同组合呢?
下面的程序解决了这个问题。
数组a[] 中既是每个国家可以派出的最多的名额。
程序执行结果为:
DEFFF
CEFFF
CDFFF
CDEFF
CCFFF
CCEFF
CCDFF
CCDEF
BEFFF
BDFFF
BDEFF
BCFFF
BCEFF
BCDFF
BCDEF
…
(以下省略,总共101行)#include <stdio.h> #define N 6 #define M 5 #define BUF 1024 void f(int a[], int k, int m, char b[]) { int i,j; if(k==N){ b[M] = 0; if(m==0) printf("%s\n",b); return; } for(i=0; i<=a[k]; i++){ for(j=0; j<i; j++) b[M-m+j] = k+'A'; ______________________; //填空位置 } } int main() { int a[N] = {4,2,2,1,1,3}; char b[BUF]; f(a,0,M,b); return 0; }仔细阅读代码,填写划线部分缺少的内容。
注意:不要填写任何已有内容或说明性文字。
-
解题思路
解决这种类型的题目我们首先要知道程序的作用。输出所有的派出组合。那么这个 f f f函数即是实现这个功能的,对于数组 a a a,其中 a [ i ] a[i] a[i]就代表了 ′ A ′ + i 'A'+i ′A′+i国最多能派出多少人,那么 b b b即是存储组合的字符串,作为输出。很明显,这是一个递归函数,其中的 k k k在递归开始为 0 0 0,在退出的时候 k = N k=N k=N,这个 k k k代表的就是我们当前正在选的国家,而 M M M即是剩余安排的人数。最核心的就是这两个 f o r for for循环,我们发现在第二个 f o r for for循环下,不断给数组 b b b赋值,赋值了 i i i个,那么这也说明,这里被选了 i i i个,那么接下来那一行其实我们就应该知道怎么填了,更改剩余人数和所填国家即可。
-
答案
f(a,k+1,m-i,b)
第九题 交换瓶子
-
问题重现
有N个瓶子,编号 1 ~ N,放在架子上。
比如有5个瓶子:
2 1 3 5 4要求每次拿起2个瓶子,交换它们的位置。
经过若干次后,使得瓶子的序号为:
1 2 3 4 5对于这么简单的情况,显然,至少需要交换2次就可以复位。
如果瓶子更多呢?你可以通过编程来解决。
输入格式为两行:
第一行: 一个正整数N(N<10000), 表示瓶子的数目
第二行:N个正整数,用空格分开,表示瓶子目前的排列情况。输出数据为一行一个正整数,表示至少交换多少次,才能完成排序。
例如,输入:
5
3 1 2 5 4程序应该输出:
3再例如,输入:
5
5 4 3 2 1程序应该输出:
2资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms -
解题思路
这道题不用想的太复杂,我们最终是要将下标与其值相等。那么倘若我们存储了一开始值的下标,那么我就知道了 i i i它所在的位置。这里用 v a l val val数组表示值, p o s pos pos数组表示位置,那么我们就可以直接遍历数组判断 v a l [ i ] = = i val[i]==i val[i]==i,如果不等于,我们就可以找到 i i i它在哪个位置,我们交换这两个位置的值即可。(交换之后记得更新 p o s pos pos)这样就保证了我们遍历的时候能将位置不对的一步就能转换。利用这样的操作,我们就能求出最少操作次数。
-
代码
/**
* @filename:交换瓶子.cbp
* @Author : pursuit
* @Blog:unique_pursuit
* @email: 2825841950@qq.com
* @Date : 2021-03-20-19.35.50
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn=1e5+5;
const int mod=1e9+7;
int n,val[maxn],pos[maxn];
void Swap(int a,int b){
int temp=val[a];
val[a]=val[b];
val[b]=temp;
}
void solve(){
int ans=0;
for(int i=1;i<=n;i++){
if(val[i]!=i){
//我们就要将是1的换到这里来。
int temp1=pos[i];//我们知道i的位置。
int temp2=val[i];
Swap(i,pos[i]);//将真正的i的位置换过去。
pos[temp2]=temp1;
ans++;
}
}
cout<<ans<<endl;
}
int main(){
while(cin>>n){
for(int i=1;i<=n;i++){
cin>>val[i];
pos[val[i]]=i;//存储这个值的位置。
}
solve();
}
return 0;
}

浙公网安备 33010602011771号