zoukankan      html  css  js  c++  java
  • 第七届蓝桥杯真题总结

    第一题  煤球数目

    有一堆煤球,堆成三角棱锥形。具体:
    第一层放1个,
    第二层3个(排列成三角形),
    第三层6个(排列成三角形),
    第四层10个(排列成三角形),
    ....
    如果一共有100层,共有多少个煤球?
    
    
    请填表示煤球总数目的数字。
    注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

    题解:注意题目说的是100层,一共有多少个啊。。规律蛮简单的,蓝桥杯第一题就找规律;不要想复杂了;第n层:(1+n)*n/2;

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    using namespace std;
    
    typedef long long LL; 
    
    void solve()
    {
        int n;
        cin >> n;
        LL ans = 0;
        for (int i = 1; i <= n; i++)
        {
            ans += (1 + i) * i / 2;
        }    
        cout << ans << endl;
    }
    
    int main()
    {
        solve();
        
        return 0;
    }

    答案:171700

    第二题:

    生日蜡烛
    
    某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。
    
    现在算起来,他一共吹熄了236根蜡烛。
    
    请问,他从多少岁开始过生日party的?
    
    请填写他开始过生日party的年龄数。
    注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字
    #include <iostream>
    using namespace std;
    
    void solve()
    {
        for (int s = 1; s <= 100; s++)
        {
            for (int e = s; e <= 100; e++)
            {
                int sum = 0;
                for (int i = s; i <= e; i++)
                {
                    sum += i; 
                }
                if (sum == 236) {
                    cout << s << " " << e << endl; 
                }
            }
        }
        
    }
    
    int main()
    {
        solve();
        
        return 0;
    }

    第三题  凑算式

          B     DEF
     A + --- + --——— = 10
          C     GHI
    
    (如果显示有问题,可以参见【图1.jpg】)
    
    这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。
    
    比如:
    6+8/3+952/714 就是一种解法,
    5+3/1+972/486 是另一种解法。
    
    这个算式一共有多少种解法?
    
    注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。

    题解:全排列问题,注意,能不用除法就不用除法,可以转换为乘法。或者除的时候用double类型。

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    
    void solve()
    {
        int res = 0;
        do {
            int A = a[0], B = a[1], C = a[2];
            int DEF = a[3]*100 + a[4]*10 + a[5];
            int GHI = a[6]*100 + a[7]*10 + a[8];
            int ans = (B*GHI + DEF*C);
            if (ans == (10 - A)*(C*GHI)) {
                res++;
            }
        } while (next_permutation(a, a + 9));
        cout << res << endl;
    }
    
    int main()
    {
        solve();
        
        return 0;    
    
    }

    手写全排列方法:

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    
    int ans; 
    const int maxn = 20;
    int num[maxn];
    bool vis[maxn];
    
    void judge()
    {
        double sum = num[0] + (double)num[1] / num[2] + (double)(num[3]*100+num[4]*10+num[5]) / 
                     (num[6]*100 + num[7]*10 + num[8]);  
        if (sum == 10){
            ans++;
        }
    }
    
    void dfs(int cur)
    {
        if (cur == 9) {
            judge();
            return;
        }
        
        for (int i = 1; i <= 9; i++)
        {
            if (!vis[i])
            {
                num[cur] = i;
                vis[i] = true;
                dfs(cur + 1);
                vis[i] = false;
            }
        }
    }
    
    void solve()
    {
        memset(vis, 0, sizeof(vis));
        dfs(0);
        cout << ans << endl;
    }
    
    int main()
    {
        solve();
        
        return 0;
    }

    第四题  快速排序

    排序在各种场合经常被用到。
    快速排序是十分常用的高效率的算法。
    
    其思想是:先选一个“标尺”,
    用它把整个队列过一遍筛子,
    以保证:其左边的元素都不大于它,其右边的元素都不小于它。
    
    这样,排序问题就被分割为两个子区间。
    再分别对子区间排序就可以了。
    
    下面的代码是一种实现,请分析并填写划线部分缺少的代码。
    
    #include <stdio.h>
    
    void swap(int a[], int i, int j)
    {
    int t = a[i];
    a[i] = a[j];
    a[j] = t;
    }
    
    int partition(int a[], int p, int r)
    {
    int i = p;
    int j = r + 1;
    int x = a[p];
    while(1){
    while(i<r && a[++i]<x);
    while(a[--j]>x);
    if(i>=j) break;
    swap(a,i,j);
    }
    ______________________;
    return j;
    }
    
    void quicksort(int a[], int p, int r)
    {
    if(p<r){
    int q = partition(a,p,r);
    quicksort(a,p,q-1);
    quicksort(a,q+1,r);
    }
    }
    
    int main()
    {
    int i;
    int a[] = {5,13,6,24,2,8,19,27,6,12,1,17};
    int N = 12;
    
    quicksort(a, 0, N-1);
    
    for(i=0; i<N; i++) printf("%d ", a[i]);
    printf("
    ");
    
    return 0;
    }
    
    注意:只填写缺少的内容,不要书写任何题面已有代码或说明性文字。

    解答:swap(a, j, p);

    #include <stdio.h>
    
    void swap(int a[], int i, int j)
    {
        int t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
    
    int partition(int a[], int p, int r)
    {
        int i = p;
        int j = r + 1;
        int x = a[p];
        while(1) {
            while(i < r && a[++i] < x);
            while(a[--j]>x);
            if(i>=j) break;
            swap(a,i,j);
        }
        swap(a, j, p);
        return j;
    }
        
    void quicksort(int a[], int p, int r)
    {
        if(p<r){
            int q = partition(a,p,r);
            quicksort(a,p,q-1);
            quicksort(a,q+1,r);
        }
    }
    
    int main()
    {
        int i;
        int a[] = {5, 13,6,24,2,8,19,27,6,12,1,17};
        int N = 12;
        
        quicksort(a, 0, N-1);
        
        for(i=0; i<N; i++) printf("%d ", a[i]);
        printf("
    ");
        
        return 0;
    }

    第五题: 抽签

    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
    ",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;
    }
    #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;
        
        //N为6个国 
        //M为5个人
        //m为剩余人数 
        if(k == N){ 
            b[M] = 0;
            if(m == 0) printf("%s
    ",b);
            return;
        }
        
        for(i=0; i<=a[k]; i++){
            for(j=0; j<i; j++) 
                b[M-m+j] = k + 'A';
            //下一个国, 剩余 m - i人 
            f(a, k+1, m - i, b);  //填空位置
        }
    }
    int main()
    {    
        int  a[N] = {4,2,2,1,1,3};
        char b[BUF];
        
        f(a, 0, M, b);
        return 0;
    }
    第六题: 方格填数
    如下的10个格子
    
    (如果显示有问题,也可以参看【图1.jpg】)
    
    填入0~9的数字。要求:连续的两个数字不能相邻。
    (左右、上下、对角都算相邻)
    
    一共有多少种可能的填数方案?
    
    请填写表示方案数目的整数。
    注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
     
    #include <iostream>
    #include <cmath>
    #include <fstream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int INF = 10000000;
    const int ROW = 3, COL = 4;
    int dir[8][2] = {{-1, 0}, {-1, 1}, {0, 1}, {1, 1},
                     {1, 0}, {1, -1}, {0, -1}, {-1, -1}};
    int ans;
    int maze[ROW][COL];
    void input();
    bool check( int r, int c);
    bool judge(int r, int c);
    void solve();
    int a[10] = {0, 1, 2, 3, 4 ,5 , 6, 7 ,8 ,9};
    
    void input()
    {
        maze[0][0] = maze[2][3] = INF;    
    }
    
    bool judge(int r, int c)
    {
        return (r >= 0 && r < 3) && (c >= 0 && c < 4);
    }
    
    //判断 
    bool check(int r, int c)
    {
        //当前位置为 (r, c)是空位置...也就是说 和周围不连续 
        if ((r == 0 && c == 0) || (r == 2 && c == 3)) return true;
        for (int k = 0; k < 8; k++) {
            int nx = r + dir[k][0], ny = c + dir[k][1];
            if (judge(nx, ny) && abs(maze[nx][ny] - maze[r][c]) == 1) {
                    return false;
                }
        }
        return true;
    }
    
    bool check2()
    {
        int i, j;
        for (i = 1; i < COL; i++) {
            maze[0][i] = a[i-1];
        }
        for (j = 0; j < COL; j++) {
            maze[1][j] = a[COL + j - 1];
        }
        for (j = 0; j < COL - 1; j++) {
            maze[2][j] = a[COL * 2 + j - 1];
        }
        
        for (i = 0; i < ROW; i++) {
            for (j = 0; j < COL; j++) {
                //不相邻,且  
                if (!check(i, j)) {        //&& (i != 0 || j != 0) && (i != 2 || j != 3)
                    return false;
                }
            }
        }
        return true;
    }
    
    void solve()
    {
        input();
        do {
            if (check2()) {
                ans++;
            }
        } while (next_permutation(a, a + 10));
    
        cout << ans << endl;
    }
    
    int main()
    {
        solve();
        return 0;    
    }
    第七题:剪邮票
    如【图1.jpg】, 有12张连在一起的12生肖的邮票。
    现在你要从中剪下5张来,要求必须是连着的。
    (仅仅连接一个角不算相连)
    比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。
    
    请你计算,一共有多少种不同的剪取方法。
    
    请填写表示方案数目的整数。
    注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
     
     
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    using namespace std;
    
    const int maxn = 14;
    int maze[3][4];
    int num[6];
    int have[13];          // 用了对从全排列中 选出来 5个数 ,进行 标志 (回溯: 标志为true后,需要换回false) 
    bool used[3][4];       //这个是 从全排列中选出来5个数,进行DFS搜索是否连续用的标志数组 , 标志为true后,不需要换回false 
    bool visit[13];        //进行全排列用的标志数组 
    int ans;
    int Count = 0;
    int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};  //方向 
    
    void init();
    void dfs_find(int r, int c);
    bool judge(int r, int c);
    void solve();
    
    void init()
    {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 4; j++) {
                maze[i][j] = i*4 + j + 1;
            }
        } 
    }
    
    bool judge(int r, int c)
    {
        return (r >= 0 && r < 3) && (c >= 0 && c < 4);
    }
    
    void dfs_find(int r, int c)
    {
        for (int i = 0; i < 4; i++)
        {
            int nx = r + dir[i][0], ny = c + dir[i][1];
            //这个位置不是have标记位置(have里标记过的元素,是全排列找到的五个元素),或者已经访问过了 
            if (judge(nx, ny) && !used[nx][ny] && have[maze[nx][ny]]) {  
                used[nx][ny] = true;    //不需要换回 false, 除非出现另外一组5个数的时候 
                Count++;                //连续的数++ 
                dfs_find(nx, ny);       //对一个点进行DFS 
            }
        }
    }
    
    void solve()
    {
        memset(have, 0, sizeof(have));
        memset(used, false, sizeof(used));
        for (int i = 1; i <= 5; i++) {
            have[ num[i] ] = 1;        //对5个数的位置进行标记 
        }
        
        for (int i = 0; i < 12; i++)
        {
            int r = i / 4;    //对应行
            int c = i % 4;    //对应列 
            if ( have[maze[r][c]] )     // 对找到的 5个数字(被标记1的),开始DFS搜索 
            {
                Count = 1;              //开始为1 
                used[r][c] = true;      //由标记的第一个数开始, 向其他标记的数 进行DFS, 找到则 Count++ 
                dfs_find(r, c);
                break;
            }
        }
        if (Count == 5) {               //全排列找到的5个数, 是相邻的, 则ans++ 
            ans++;
        }
    }
    //创建5个数的组合 
    void Start_DFS(int cur)
    {
        if (cur == 6)   //找到了5个数 
        {
            solve();    //对找到的5个数,进行排列组合 
            return;
        }
        
        //1到12 这 12个数 挨个遍历 -- 并进行DFS搜索 
        for (int i = num[cur - 1] + 1; i < 13; i++)    
        {
            if (!visit[i])          
            {
                visit[i] = true;
                num[cur] = i;       //存数,  对12个数进行全排列,从中选5个数,再进行排列组合 
                Start_DFS(cur + 1); //下一个数
                visit[i] = false;   
            }
        } 
    }
    
    int main()
    {
        init();
        Start_DFS(1);
        printf("%d
    ", ans);
    }

    算法思路:

    1. 先全排列,从全排列1~12,从中选5个数,进行排列组合;

    2. 对选中的5个数标志;

    3. 循环找到第一个 第一个被标志的位置,并DFS递归寻找,他的dir方向的数字,是否是从全排列中选出来的其他数字.

    详细看注释.

    第八题  四平方和

    四平方和定理,又称为拉格朗日定理:
    每个正整数都可以表示为至多4个正整数的平方和。
    如果把0包括进去,就正好可以表示为4个数的平方和。
    
    比如:
    5 = 0^2 + 0^2 + 1^2 + 2^2
    7 = 1^2 + 1^2 + 1^2 + 2^2^符号表示乘方的意思)
    
    对于一个给定的正整数,可能存在多种平方和的表示法。
    要求你对4个数排序:
    0 <= a <= b <= c <= d
    并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法
    
    程序输入为一个正整数N (N<5000000)
    要求输出4个非负整数,按从小到大排序,中间用空格分开
    
    例如,输入:
    5
    则程序应该输出:
    0 0 1 2
    再例如,输入:
    12
    则程序应该输出:
    0 2 2 2
    再例如,输入:
    773535
    则程序应该输出:
    1 1 267 838
    
    资源约定:
    峰值内存消耗 < 256M
    CPU消耗 < 3000ms

    解答:可能会超时.......但是这里秒出结果了...

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    
    void solve()
    {
        int N;
        cin >> N;
        
        //1150*1150*4 = 5290000
        for (int a = 0; a <= 1150; a++)
        {
            if (a*a >= N) continue;
            for (int b = a; b <= 1150; b++)
            {
                if (a*a + b*b >= N) continue;
                for (int c = b; c <= 1150; c++)
                {
                    if (a*a + b*b + c*c >= N) continue;
                    double d = sqrt(N - a*a - b*b - c*c);
                    if (d == (int)d) {
                        printf("%d %d %d %.f
    ",a,b,c, d);
                            return;
                    }
                }
            }
        }
    }
    
    int main()
    {
        solve();
        
        return 0;
        
    }

    第九题: 交换瓶子

    有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

    题解:感觉是一个选择排序......不知道对不对.....

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    const int maxn = 10000 + 20;
    int num[maxn];
    
    void solve()
    {
        int N;
        int ans = 0;
        scanf("%d", &N);
        
        for (int i = 0; i < N; i++)
        {
            scanf("%d", &num[i]);
        }
        
        for (int i = 0; i < N - 1; i++)
        {
            int min = i;
            for (int j = min + 1; j < N; j++)
            {
                if (num[min] > num[j]) {
                    min = j;
                }
            }
            if (min != i) {
                swap(num[min], num[i]);
                ans++;
            }
        }
    //    for (int i = 0; i < N; i++) {
    //        cout << num[i] << " ";
    //    }
    //    cout << endl;
        cout << ans << endl;
    }
    
    int main()
    {
        solve();
        
        return 0;
    }
  • 相关阅读:
    常见运算符_python
    hibernate中的二级缓存
    事务的隔离级别
    java hibernate 一对多和多对多映射关系总结
    hibernate中集合映射总结
    java中静态代码块之我的理解
    select下拉表达设置选中,获取选中项,change
    jquery checkbox设置选中,全选,反选,取值
    javaWeb建立一个简单三层项目具体步骤
    java 异步实现省市联动
  • 原文地址:https://www.cnblogs.com/douzujun/p/8614192.html
Copyright © 2011-2022 走看看