蓝桥杯近三年初赛题之二(16年b组)

1、

煤球数目

有一堆煤球,堆成三角棱锥形。具体:
第一层放1个,
第二层3个(排列成三角形),
第三层6个(排列成三角形),
第四层10个(排列成三角形),
....
如果一共有100层,共有多少个煤球?

请填表示煤球总数目的数字。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

找规律,第n层是n-1层煤球的个数加上n,答案为:171700。代码如下:

 1 #include<stdio.h>
 2 int main()
 3 {
 4     int i,a[101],s=0;
 5     a[1]=1;
 6     for(i=2;i<101;i++)
 7         a[i]=a[i-1]+i;
 8     for(i=1;i<101;i++)
 9     {
10         s+=a[i];
11         printf("%d ",a[i]);
12     }
13     printf("
%d",s);
14     return 0;
15 }

2、

生日蜡烛

某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。

现在算起来,他一共吹熄了236根蜡烛。

请问,他从多少岁开始过生日party的?

请填写他开始过生日party的年龄数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

一个二重循环暴力解决,答案为:26。代码如下:

 1 #include<stdio.h>
 2 int main()
 3 {
 4     int s,i,j;
 5     for(i=1;i<100;i++)
 6     {
 7         s=0;
 8         for(j=i;j<100;j++)
 9         {
10             s+=j;
11             if(s>236)
12                 break;
13             if(s==236)
14                 printf("%d",i);
15         }
16     }
17     return 0;
18 }

3、

凑算式

       B      DEF
A + --- + ------- = 10
       C      GHI


这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。

比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。

这个算式一共有多少种解法?

注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。

一个深搜解决,答案为29。代码如下:

#include<stdio.h>
int sum=0;
int a[9];
int vis[10];
void dfs(int cur)
{
    int i;
    if(cur==9)
    {
        int x1,x2;
        x1=a[1]*(a[6]*100+a[7]*10+a[8])+a[2]*(a[3]*100+a[4]*10+a[5]);
        x2=a[2]*(a[6]*100+a[7]*10+a[8]);
        if(a[0]+x1/x2==10&&x1%x2==0)
        {
            for(i=0;i<9;i++)
            {
                printf("%d ",a[i]);
            }
            printf("
");
            sum++;
        }
    }
    else for(i=1;i<10;i++)
    {
        if(!vis[i])
        {
            vis[i]=1;
            a[cur]=i;
            dfs(cur+1);
            vis[i]=0;
        }
    }
}
int main()
{
    dfs(0);
    printf("%d",sum);
    return 0;
}

4、


快速排序

排序在各种场合经常被用到。
快速排序是十分常用的高效率的算法。

其思想是:先选一个“标尺”,
用它把整个队列过一遍筛子,
以保证:其左边的元素都不大于它,其右边的元素都不小于它。

这样,排序问题就被分割为两个子区间。
再分别对子区间排序就可以了。

下面的代码是一种实现,请分析并填写划线部分缺少的代码。


#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,p,j)。

5、


抽签

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;
}

仔细阅读代码,填写划线部分缺少的内容。

注意:不要填写任何已有内容或说明性文字。

这题我是猜着写的,结果对了。答案为:f(a,k+1,m-i,b)。

6、


方格填数

如下的10个格子
     +--+--+--+
   |    |    |    |
+--+--+--+--+
|  |    |    |    |
+--+--+--+--+
|  | |    |
+--+--+--+

填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)

一共有多少种可能的填数方案?

请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

一个深搜,但我条件没写对,答案是:1580。转一下别人的代码:

 1 #include <stdio.h>  
 2 #include <math.h>  
 3 int flag[3][4]; //表示哪些可以填数  
 4 int mpt[3][4]; //填数  
 5 bool visit[10];  
 6 int ans = 0;  
 7 void init()   //初始化  
 8 {  
 9     int i,j;  
10     for(i = 0 ; i < 3 ; i ++)  
11         for(j = 0 ; j < 4 ; j ++)  
12             flag[i][j] = 1;  
13     flag[0][0] = 0;  
14     flag[2][3] = 0;  
15 }  
16   
17 void Solve()  
18 {  
19     int dir[8][2] = { 0,1,0,-1,1,0,-1,0,1,1,1,-1,-1,1,-1,-1};  
20     int book = true;  
21     for(int i = 0 ; i < 3 ; i ++)  
22     {  
23         for(int j = 0 ; j < 4; j ++)  
24         {  
25             //判断每个数周围是否满足  
26             if(flag[i][j] == 0)continue;  
27             for( int k = 0 ; k < 8 ; k ++)  
28             {  
29                 int x,y;  
30                 x = i + dir[k][0];  
31                 y = j + dir[k][1];  
32                 if(x < 0 || x >= 3 || y < 0 || y >= 4 || flag[x][y] == 0) continue;  
33                 if(abs(mpt[x][y] - mpt[i][j]) == 1)  book = false;  
34             }  
35         }  
36     }  
37     if(book) ans ++;  
38 }  
39   
40   
41 void dfs(int index)  
42 {  
43     int x,y;  
44     x = index / 4;  
45     y = index % 4;  
46     if( x == 3)  
47     {  
48         Solve();  
49         return;  
50     }  
51     if(flag[x][y])  
52     {  
53         for(int i = 0 ; i < 10 ; i ++)  
54         {  
55             if(!visit[i])  
56             {  
57                 visit[i] = true;  
58                 mpt[x][y] = i;  
59                 dfs(index+1);  
60                 visit[i] = false;  
61             }  
62         }  
63     }  
64     else  
65     {  
66         dfs(index+1);  
67     }  
68 }  
69 int main()  
70 {  
71     init();  
72     dfs(0);  
73     printf("%d
",ans);  
74     return 0;  
75 } 

7、

剪邮票

如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

请你计算,一共有多少种不同的剪取方法。

请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

 

同样是深搜,但我不会走格子,所以这一题我也GG了,答案为:116。转一下别人代码:

 1 #include <stdio.h>  
 2 #include <string.h>  
 3 int mpt[3][4];  
 4 int mpt_visit[3][4];  
 5 int num[6];   
 6 int have[13];  
 7 int visit[13];  
 8 int ans = 0;  
 9 int Count = 0;  
10   
11 void init()  
12 {  
13     int k = 1;  
14     for(int i = 0 ; i < 3 ; i ++)  
15         for(int j = 0 ; j < 4 ; j ++)  
16         {  
17             mpt[i][j] = k;  
18             k ++;  
19         }  
20 }  
21 int dir[4][2] = {0,1,0,-1,-1,0,1,0};  
22 //判断五个数是否能连在一起  
23 void dfs_find(int x,int y)  
24 {  
25     for(int i = 0 ; i < 4 ; i++)  
26     {  
27         int tx,ty;  
28         tx = x + dir[i][0];  
29         ty = y + dir[i][1];  
30         if(tx < 0 || tx >= 3 || ty < 0 || ty >= 4) continue;  
31         if(have[mpt[tx][ty]] == 0 || mpt_visit[tx][ty])continue;  
32         mpt_visit[tx][ty] = 1;  
33         Count ++;  
34         dfs_find(tx,ty);  
35     }  
36 }  
37   
38 void Solve()  
39 {  
40     int i;  
41     memset(have,0,sizeof(have));  
42     memset(mpt_visit,0,sizeof(mpt_visit));  
43     for(i = 1; i < 6 ; i ++) have[num[i]] = 1;  
44     for(i = 0 ; i < 12 ; i ++)  
45     {  
46         int x,y;  
47         x = i / 4;  
48         y = i % 4;  
49         if(have[mpt[x][y]])  
50         {  
51             Count = 1;  
52             mpt_visit[x][y] =1;  
53             dfs_find(x,y);  
54             break;  
55         }  
56     }  
57     if(Count == 5)  
58     {  
59         ans ++;  
60     }  
61 }  
62   
63 //创建5个数的组合  
64 void dfs_creat(int index)  
65 {  
66     if(index == 6)  
67     {  
68         Solve();  
69         return;  
70     }  
71     for(int i = num[index-1] + 1; i < 13 ; i ++)  
72     {  
73         if(!visit[i])  
74         {  
75             visit[i] = true;  
76             num[index] = i;  
77             dfs_creat(index+1);  
78             visit[i] = false;  
79         }  
80     }  
81 }  
82   
83 int main()  
84 {  
85     init();  
86     dfs_creat(1);  
87     printf("%d
",ans);  
88     return 0;  
89 } 

 8、

四平方和

四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多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

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

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

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

提交时,注意选择所期望的编译器类型。

这题代码自己写的超时了,转一下别人O(n)的代码(先把两个平方数能相加的到的数字球出来然后记录):

 1 #include <stdio.h>  
 2 #include <math.h>  
 3 int mpt[5000010] ={0};  //mpt[i] = 1表示i 能够用两个完全平方数相加而得。  
 4 int n;  
 5 void init()  
 6 {  
 7     for(int i = 0 ; i*i <= n ; i ++)  
 8         for(int j = 0 ; j*j <=n ; j ++)  
 9             if(i*i+j*j <= n) mpt[i*i+j*j] = 1;  
10 }  
11 int main()  
12 {  
13       
14     int flag = false;  
15     scanf("%d",&n);  
16     init();  
17     for(int i = 0 ; i * i <= n ; i ++)  
18     {  
19         for(int j = 0 ; j * j <= n ; j ++){  
20             if(mpt[n - i*i - j*j] == 0) continue;   //如果剩下的差用两个完全平方数不能组合出来就不继续  
21             for(int k = 0 ; k * k <= n ; k ++)  
22             {  
23                 int temp = n - i*i - j*j - k*k;  
24                 double l = sqrt((double) temp);  
25                 if(l == (int)l )  
26                 {  
27                     printf("%d %d %d %d
",i,j,k,(int)l);  
28                     flag = true;  
29                     break;  
30                 }  
31             }  
32             if(flag)break;  
33         }  
34         if(flag)break;  
35     }  
36     return 0;  
37 } 

9、

交换瓶子

有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

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

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

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

提交时,注意选择所期望的编译器类型。

自己的代码超时,同样转一下别人的代码:

#include <stdio.h>  
#include <math.h>  
int arr[10010];  
int flag[10010];  
int main()  
{  
    int ans = 0;  
    int n,i;  
    scanf("%d",&n);  
    for(i = 1 ; i <= n ; i ++) scanf("%d",&arr[i]);  
    for(i = 1 ; i <= n ; i ++ )flag[arr[i]] = i;  
    for(i = 1 ; i <= n ; i ++)  
    {  
        if( i != arr[i] )  
        {  
            int x = arr[i];  
            arr[i] ^= arr[flag[i]] ^= arr[i] ^= arr[flag[i]];  
            flag[i] ^= flag[x] ^= flag[i] ^= flag[x];  
            ans ++;  
        }  
    }  
    printf("%d
",ans);  
    return 0;  
}

10、

最大比例

X星球的某个大奖赛设了M级奖励。每个级别的奖金是一个正整数。
并且,相邻的两个级别间的比例是个固定值。
也就是说:所有级别的奖金数构成了一个等比数列。比如:
16,24,36,54
其等比值为:3/2

现在,我们随机调查了一些获奖者的奖金数。
请你据此推算可能的最大的等比值。

输入格式:
第一行为数字 N (0<N<100),表示接下的一行包含N个正整数
第二行N个正整数Xi(Xi<1 000 000 000 000),用空格分开。每个整数表示调查到的某人的奖金数额

要求输出:
一个形如A/B的分数,要求A、B互质。表示可能的最大比例系数

测试数据保证了输入格式正确,并且最大比例是存在的。

例如,输入:
3
1250 200 32

程序应该输出:
25/4

再例如,输入:
4
3125 32 32 200

程序应该输出:
5/2

再例如,输入:
3
549755813888 524288 2

程序应该输出:
4/1

资源约定:
峰值内存消耗 < 256M
CPU消耗 < 3000ms

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

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

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

提交时,注意选择所期望的编译器类型。

这题不会,具体思路移步至末尾他人blog,转一下他人代码:

 1 #include <stdio.h>  
 2 #include <algorithm>  
 3 #include <queue>  
 4 using namespace std;  
 5 #define LL long long  
 6 struct fs  
 7 {  
 8     LL up,down;  
 9 };  
10 int n;  
11 LL arr[110];  
12 fs Fs[110];  
13   
14 bool cmp(LL a,LL b)  
15 {  
16     return a > b;  
17 }  
18   
19 LL Gcd(LL a,LL b)  
20 {  
21     if( b == 0 )return a;  
22     return Gcd(b,a%b);  
23 }  
24 LL Get(LL a, LL b)  
25 {  
26     if( a < b) a ^= b ^= a ^= b;  
27     LL v[30];  
28     queue<LL>team;  
29     if( a == b || a / b == a) return b;  
30     v[0] = a, v[1] = b;  
31     v[2] = a / b;  
32     int top = 3,i,j;  
33     team.push(a/b);  
34     while(team.size())  
35     {  
36         LL now = team.front();  
37         team.pop();  
38         for(i = 0 ; i < top ; i ++)  
39         {  
40             LL temp = (v[i] > now) ? v[i] / now : now / v[i];  
41             bool find = false;  
42             for(j = 0 ; j < top ; j ++)  
43                 if( v[j] == temp) find = true;  
44             if(find == true) continue;  
45             team.push(temp);  
46             v[top++] = temp;  
47         }  
48     }  
49     LL ans = v[0];  
50     for(i = 0 ; i < top ; i ++)   
51         if(v[i] != 1)   
52         {  
53             ans = v[i];  
54             break;  
55         }  
56     for(i = 0 ; i < top ; i ++)  
57         if( v[i] < ans && v[i] != 1) ans = v[i];  
58     return ans;  
59 }  
60 int main()  
61 {  
62     int i,j;  
63     scanf("%d",&n);  
64     for(i = 0 ; i < n ; i ++) scanf("%lld",&arr[i]);  
65     sort(arr,arr+n,cmp);  
66     int top = 1;  
67     for(i = 1; i < n ; i ++)  
68         if(arr[i] != arr[i-1]) arr[top++] = arr[i];  
69     n = top;  
70     for(i = 0 ; i < n - 1; i ++)  
71     {  
72         LL gcd = Gcd(arr[i],arr[i+1]);  
73         Fs[i].up = arr[i] / gcd;  
74         Fs[i].down = arr[i+1] / gcd;  
75     }  
76     LL x = Fs[0].up;  
77     for(i = 0 ; i < n - 1 ; i ++)  
78         x = Get(x,Fs[i].up);  
79     LL y = Fs[0].down;  
80     for(i = 0 ; i < n - 1; i ++)  
81         y = Get(y,Fs[i].down);  
82     printf("%lld/%lld
",x,y);  
83     return 0;  
84 } 

部分代码转自:https://blog.csdn.net/y1196645376/article/details/50938608

原文地址:https://www.cnblogs.com/search-the-universe/p/y2016.html