第七届蓝桥杯(软件类)省赛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 aiai1=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;
}

posted @ 2022-03-26 16:49  unique_pursuit  阅读(33)  评论(0)    收藏  举报