第八届蓝桥杯省赛练习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/bmicnj/article/details/79773200
3、

标题:承压计算


X星球的高科技实验室中整齐地堆放着某批珍贵金属原料。


每块金属原料的外形、尺寸完全一致,但重量不同。
金属材料被严格地堆放成金字塔形。


                             7 
                            5 8 
                           7 8 8 
                          9 2 7 2 
                         8 1 4 9 1 
                        8 1 8 8 4 1 
                       7 9 6 1 4 5 4 
                      5 6 5 5 6 9 5 6 
                     5 5 4 7 9 3 5 5 1 
                    7 5 7 9 7 4 7 3 3 1 
                   4 6 4 5 5 8 8 3 2 4 3 
                  1 1 3 3 1 6 6 5 5 4 4 2 
                 9 9 9 2 1 9 1 9 2 9 5 7 9 
                4 3 3 7 7 9 3 6 1 3 8 8 3 7 
               3 6 8 1 5 3 9 5 8 3 8 1 8 3 3 
              8 3 2 3 3 5 5 8 5 4 2 8 6 7 6 9 
             8 1 8 1 8 4 6 2 2 1 7 9 4 2 3 3 4 
            2 8 4 2 2 9 9 2 8 3 4 9 6 3 9 4 6 9 
           7 9 7 4 9 7 6 6 2 8 9 4 1 8 1 7 2 1 6 
          9 2 8 6 4 2 7 9 5 4 1 2 5 1 7 3 9 8 3 3 
         5 2 1 6 7 9 3 2 8 9 5 5 6 6 6 2 1 8 7 9 9 
        6 7 1 8 8 7 5 3 6 5 4 7 3 4 6 7 8 1 3 2 7 4 
       2 2 6 3 5 3 4 9 2 4 5 7 6 6 3 2 7 2 4 8 5 5 4 
      7 4 4 5 8 3 3 8 1 8 6 3 2 1 6 2 6 4 6 3 8 2 9 6 
     1 2 4 1 3 3 5 3 4 9 6 3 8 6 5 9 1 5 3 2 6 8 8 5 3 
    2 2 7 9 3 3 2 8 6 9 8 4 4 9 5 8 2 6 3 4 8 4 9 3 8 8 
   7 7 7 9 7 5 2 7 9 2 5 1 9 2 6 5 3 9 3 5 7 3 5 4 2 8 9 
  7 7 6 6 8 7 5 5 8 2 4 7 7 4 7 2 6 9 2 1 8 2 9 8 5 7 3 6 
 5 9 4 5 5 7 5 5 6 3 5 3 9 5 8 9 5 4 1 2 6 1 4 3 5 3 2 4 1 
X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X 


其中的数字代表金属块的重量(计量单位较大)。
最下一层的X代表30台极高精度的电子秤。


假设每块原料的重量都十分精确地平均落在下方的两个金属块上,
最后,所有的金属块的重量都严格精确地平分落在最底层的电子秤上。
电子秤的计量单位很小,所以显示的数字很大。


工作人员发现,其中读数最小的电子秤的示数为:2086458231


请你推算出:读数最大的电子秤的示数为多少?


注意:需要提交的是一个整数,不要填写任何多余的内容。

下面一行的数等于上面相邻的两个(或一个)数的和的一半加自身值,要注意的是在计算过程中求值,得出的结果小数位一定为0.

code:



#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int main()
{
    double a[40][40]= {0};
    int n;
    scanf("%d", &n);
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=i; j++) {
            scanf("%lf", &a[i][j]);
        }
    }
    for(int i=2; i<=n+1; i++) {
        for(int j=1; j<=i; j++) {
            if(j==1) {
                a[i][j] += a[i-1][j]/2;
            }
            else if(j == i) {
                a[i][j] += a[i-1][j-1]/2;
            }
            else {
                a[i][j] += (a[i-1][j-1] + a[i-1][j])/2;
            }
        }
    }
    int maxi=1,mini=1;
    for(int i=1; i<=n+1; i++){
        printf("%lf\n", a[n+1][i]);
        if(a[n+1][i] > a[n+1][maxi]) maxi = i;
        if(a[n+1][i] < a[n+1][mini]) mini = i;
    }
    printf("%lf=\n", a[n+1][mini]);
    printf("%lf=\n", a[n+1][maxi]);
    printf("%lf=\n", a[n+1][maxi] * 2086458231 /a[n+1][mini] );//在计算过程中求值,得出的结果是一个整数值72665192664.000000

    printf("%lf==\n", 135.349469 * 2086458231 /3.886331 ); // 因为浮点型,带入运行输出的值会有误差72665198526.972961
    return 0;
}
/*
7
5 8
7 8 8
9 2 7 2
8 1 4 9 1
8 1 8 8 4 1
7 9 6 1 4 5 4
5 6 5 5 6 9 5 6
5 5 4 7 9 3 5 5 1
7 5 7 9 7 4 7 3 3 1
4 6 4 5 5 8 8 3 2 4 3
1 1 3 3 1 6 6 5 5 4 4 2
9 9 9 2 1 9 1 9 2 9 5 7 9
4 3 3 7 7 9 3 6 1 3 8 8 3 7
3 6 8 1 5 3 9 5 8 3 8 1 8 3 3
8 3 2 3 3 5 5 8 5 4 2 8 6 7 6 9
8 1 8 1 8 4 6 2 2 1 7 9 4 2 3 3 4
2 8 4 2 2 9 9 2 8 3 4 9 6 3 9 4 6 9
7 9 7 4 9 7 6 6 2 8 9 4 1 8 1 7 2 1 6
9 2 8 6 4 2 7 9 5 4 1 2 5 1 7 3 9 8 3 3
5 2 1 6 7 9 3 2 8 9 5 5 6 6 6 2 1 8 7 9 9
6 7 1 8 8 7 5 3 6 5 4 7 3 4 6 7 8 1 3 2 7 4
2 2 6 3 5 3 4 9 2 4 5 7 6 6 3 2 7 2 4 8 5 5 4
7 4 4 5 8 3 3 8 1 8 6 3 2 1 6 2 6 4 6 3 8 2 9 6
1 2 4 1 3 3 5 3 4 9 6 3 8 6 5 9 1 5 3 2 6 8 8 5 3
2 2 7 9 3 3 2 8 6 9 8 4 4 9 5 8 2 6 3 4 8 4 9 3 8 8
7 7 7 9 7 5 2 7 9 2 5 1 9 2 6 5 3 9 3 5 7 3 5 4 2 8 9
7 7 6 6 8 7 5 5 8 2 4 7 7 4 7 2 6 9 2 1 8 2 9 8 5 7 3 6
5 9 4 5 5 7 5 5 6 3 5 3 9 5 8 9 5 4 1 2 6 1 4 3 5 3 2 4 1
X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
*/
4、


标题:方格分割


6x6的方格,沿着格子的边线剪开成两部分。
要求这两部分的形状完全相同。


如图:p1.png, p2.png, p3.png 就是可行的分割法。


试计算:
包括这3种分法在内,一共有多少种不同的分割方法。
注意:旋转对称的属于同一种分割法。


请提交该整数,不要填写任何多余的内容或说明文字。

参考题解,沿着小方格的边剪出来后的图形是相等的,两个相等图形在原图中是中心对称的,DFS从中心点(3,3)开始搜索,上下左右进行移动,标记的时候和它中心对称的点也要标记,知道走到边界说明一次裁剪完成,因为旋转对称是同一种结果,所以结果除以4.

code:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int vis[10][10];
int dir[4][2] = {0,1,1,0,0,-1,-1,0};
int n = 6,ans=0;
void DFS(int x, int y) {
    if(x == 0 || y == 0 || x == n || y == n) {
        ans ++;
        return ;
    }
    for(int i=0; i<4; i++) {
        int xx = x + dir[i][0];
        int yy = y + dir[i][1];
        if(vis[xx][yy])
            continue;
        vis[xx][yy] = 1;
        vis[n-xx][n-yy] = 1;
        DFS(xx, yy);
        //回溯
        vis[xx][yy] = 0;
        vis[n-xx][n-yy] = 0;
    }
}
int main()
{

    memset(vis, 0,sizeof(vis));
    vis[n/2][n/2] = 1;
    DFS(n/2, n/2);
    printf("%d\n", ans/4);
    return 0;
}

8、

标题:包子凑数


小明几乎每天早晨都会在一家包子铺吃早餐。他发现这家包子铺有N种蒸笼,其中第i种蒸笼恰好能放Ai个包子。每种蒸笼都有非常多笼,可以认为是无限笼。


每当有顾客想买X个包子,卖包子的大叔就会迅速选出若干笼包子来,使得这若干笼中恰好一共有X个包子。比如一共有3种蒸笼,分别能放3、4和5个包子。当顾客想买11个包子时,大叔就会选2笼3个的再加1笼5个的(也可能选出1笼3个的再加2笼4个的)。


当然有时包子大叔无论如何也凑不出顾客想买的数量。比如一共有3种蒸笼,分别能放4、5和6个包子。而顾客想买7个包子时,大叔就凑不出来了。


小明想知道一共有多少种数目是包子大叔凑不出来的。


输入
----
第一行包含一个整数N。(1 <= N <= 100)
以下N行每行包含一个整数Ai。(1 <= Ai <= 100)  


输出
----
一个整数代表答案。如果凑不出的数目有无限多个,输出INF。


例如,
输入:
2  
4  
5   


程序应该输出:
6  


再例如,
输入:
2  
4  
6    


程序应该输出:
INF


样例解释:
对于样例1,凑不出的数目包括:1, 2, 3, 6, 7, 11。  
对于样例2,所有奇数都凑不出来,所以有无限多个。  


资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 1000ms




请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。


注意:
main函数需要返回0;
只使用ANSI C/ANSI C++ 标准;
不要调用依赖于编译环境或操作系统的特殊函数。
所有依赖的函数必须明确地在源文件中 #include <xxx>
不能通过工程设置而省略常用头文件。


提交程序时,注意选择所期望的语言类型和编译器类型。

分析:题意简单,就是看给出的数中能否选择一部分或全部的数,相加能不能等于任意给出的整数,输出不能的个数。

没有想出怎么做,看题解说是扩展欧几里得和完全背包的知识(都忘掉了QAQ),还有个“只要给出所有数的最大公约数!=1”,就有无穷解,不然是有限个解。。。。。。除了这个,以我的理解,就是打表,对n个数进行逐个累加,和为下标,标记为1。因为Ai<=100,只要遍历到100*100.

code:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int n,a[110];
int mark[10010];
int cnt = 0;

int GCD(int a, int b) {
    if(b==0) return a;
    return GCD(b, a%b);
}
int main()
{


    scanf("%d", &n);
    memset(mark, 0, sizeof(mark));
    for(int i=0; i<n; i++) {
        scanf("%d", &a[i]);
        mark[a[i]] = 1;
    }
    int g = a[0];
    for(int i=1; i<n; i++) {
        g = GCD(g, a[i]);
    }
    if(g != 1) {
        printf("INF\n");
    }
    else { //打表
        mark[0] = 1;
        for(int i=0; i<n; i++) {
           for(int j=0; j+a[i] < 10010; j++) {
               if(mark[j])
                    mark[j+a[i]] = 1;
           }
        }
        for(int i=0; i<10010; i++) {
            if(!mark[i])
                cnt++;
        }
        printf("%d\n",cnt);
    }

    return 0;
}

下面是参考的题解的链接:点击打开链接

**没有题源,上面的代码没有提交,只是个人练习QAQ



猜你喜欢

转载自blog.csdn.net/bmicnj/article/details/79773200