XX第七届蓝桥杯CC++B组题解.docx

上传人:b****6 文档编号:7869362 上传时间:2023-01-26 格式:DOCX 页数:27 大小:88.18KB
下载 相关 举报
XX第七届蓝桥杯CC++B组题解.docx_第1页
第1页 / 共27页
XX第七届蓝桥杯CC++B组题解.docx_第2页
第2页 / 共27页
XX第七届蓝桥杯CC++B组题解.docx_第3页
第3页 / 共27页
XX第七届蓝桥杯CC++B组题解.docx_第4页
第4页 / 共27页
XX第七届蓝桥杯CC++B组题解.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

XX第七届蓝桥杯CC++B组题解.docx

《XX第七届蓝桥杯CC++B组题解.docx》由会员分享,可在线阅读,更多相关《XX第七届蓝桥杯CC++B组题解.docx(27页珍藏版)》请在冰豆网上搜索。

XX第七届蓝桥杯CC++B组题解.docx

XX第七届蓝桥杯CC++B组题解

第一题

煤球数目

有一堆煤球,堆成三角棱锥形。

具体:

第一层放1个,

第二层3个(排列成三角形),

第三层6个(排列成三角形),

第四层10个(排列成三角形),

....

如果一共有100层,共有多少个煤球?

请填表示煤球总数目的数字。

注意:

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

这道题坑死了,第一次看堆成三角棱锥形,草稿本画半天都没画出个三角棱锥。

后来单独看每句话才知道每层一个三角形叠起来就是三角棱锥。

我去。

看懂题目这个题目就很简单了,每层的个数是上层的个数加上层数,意思就是An=An-1+n,然而题目是求的前100层一共多少煤球。

所以是Sn.代码双重for循环就出来了。

答案是:

171700

1.#include  

2.int main()  

3.{  

4.    int a[101] ={0};  

5.    for(int i = 1 ; i < 101 ; i ++)  

6.        a[i] = a[i-1] + i;  

7.    int ans = 0;  

8.    for(int j = 1 ; j < 101 ; j ++)  

9.        ans += a[j];  

10.    printf("%d\n",ans);  

11.    return 0;  

12.}  

第二题:

生日蜡烛

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

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

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

请填写他开始过生日party的年龄数。

注意:

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

呵呵,水题,但是出题人不严谨啊!

怎么就不能考虑万一他今年236岁呢....好了不说了强迫症犯了。

蓝桥杯这种不像acm的题目的,能暴力直接暴力。

不用想太多。

直接从1~236枚举start,end分别表示他开始过生日的年龄和今年的年龄,然后计算之间吹蜡烛的总和如果等于236就输出start,end. 答案是:

26

1.#include  

2.int main()  

3.{  

4.    int start,end;  

5.    for(start = 1 ; start < 236 ; start ++)  

6.    {  

7.        for( end = start ; end < 236 ; end ++ )  

8.        {  

9.            int sum = 0;  

10.            for(int i = start; i <= end; i ++)  

11.                sum += i;  

12.            if( sum == 236)  

13.            {  

14.                printf("start :

 %d end :

 %d\n",start,end);  

15.            }  

16.        }  

17.    }  

18.    return 0;  

19.}  

第三题:

凑算式

    B   DEF

A+—+-———=10

    C   GHI

(如果显示有问题,可以参见【图1.jpg】)

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

比如:

6+8/3+952/714就是一种解法,

5+3/1+972/486是另一种解法。

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

注意:

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

这个题不多说了,直接暴力生成9的全排列然后去验证等式是否成立,只是验证的时候如果防止精度问题可以通分把除法变成乘法。

答案是:

29

1.#include  

2.int ans = 0;  

3.int num[10];  

4.bool visit[10];  

5.  

6.void Solve()  

7.{  

8.    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]);  

9.    if(sum == 10)  

10.    {  

11.        ans ++;  

12.    }  

13.}  

14.  

15.void dfs(int index)  

16.{  

17.    if(index == 9)  

18.    {  

19.        Solve();  

20.        return ;  

21.    }  

22.    for(int i = 1 ; i < 10 ; i ++)  

23.    {  

24.        if(!

visit[i])  

25.        {  

26.            visit[i] = true;  

27.            num[index] = i;  

28.            dfs(index+1);  

29.            visit[i] = false;  

30.        }  

31.    }  

32.}  

33.  

34.int main()  

35.{  

36.    dfs(0);  

37.    printf("%d\n",ans);  

38.    return 0;  

39.}  

第四题:

快速排序

排序在各种场合经常被用到。

快速排序是十分常用的高效率的算法。

其思想是:

先选一个“标尺”,

用它把整个队列过一遍筛子,

以保证:

其左边的元素都不大于它,其右边的元素都不小于它。

这样,排序问题就被分割为两个子区间。

再分别对子区间排序就可以了。

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

#include

voidswap(inta[],inti,intj)

{

intt=a[i];

a[i]=a[j];

a[j]=t;

}

intpartition(inta[],intp,intr)

{

inti=p;

intj=r+1;

intx=a[p];

while

(1){

while(i

while(a[--j]>x);

if(i>=j)break;

swap(a,i,j);

}

______________________;

returnj;

}

voidquicksort(inta[],intp,intr)

{

if(p

intq=partition(a,p,r);

quicksort(a,p,q-1);

quicksort(a,q+1,r);

}

}

intmain()

{

inti;

inta[]={5,13,6,24,2,8,19,27,6,12,1,17};

intN=12;

quicksort(a,0,N-1);

for(i=0;i

printf("\n");

return0;

}

注意:

只填写缺少的内容,不要书写任何题面已有代码或说明性文字。

这个题目如果接触过快排,了解过快速排序的原理的应该是送分题目,只不过快排单步(就是将一堆数按照某个数作为基准数分成左右两堆)这个实现方式有几种代码表现。

在这里答案是swap(a,p,j).

第五题:

抽签

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

#defineN6

#defineM5

#defineBUF1024

voidf(inta[],intk,intm,charb[])

{

inti,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

______________________;//填空位置

}

}

intmain()

{

inta[N]={4,2,2,1,1,3};

charb[BUF];

f(a,0,M,b);

return0;

}

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

注意:

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

这个题目是这样的,对于f(inta[],intk,intm,charb[]).a[]是每个国家的最多指派人数,k表示当前是哪个国家,m表示还需要派送几个人(可以为负数).b表示已经派送的人的字符串。

所以这个题目在递归中间的的第一个循环表示从0~a[i]中让i国选择指派人数,内循环只是向b[]记录的过程。

所以答案是f(a,k+1,m-i,b).   因为这里I=j.应该 f(a,k+1,m-j,b)也可以。

第六题:

方格填数

如下的10个格子

(如果显示有问题,也可以参看【图1.jpg】)

填入0~9的数字。

要求:

连续的两个数字不能相邻。

(左右、上下、对角都算相邻)

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

请填写表示方案数目的整数。

注意:

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

这个题目题目有点表述不明,不知道0~9可不可以重复使用。

我当时做的时候是当作不可以重复使用来处理的。

那么这里我就先当作不可重复使用来讲解。

这里题目还是一样先往里面填数。

用生成排列的形式。

填写完了之后再判断是否可行。

答案是:

1580

1.#include   

2.#include   

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\n",ans);  

74.    return 0;  

75.}  

第七题:

剪邮票

如【图1】,有12张连在一起的12生肖的邮票。

现在你要从中剪下5张来,要求必须是连着的。

(仅仅连接一个角不算相连)

比如,【图2】,【图3】中,粉红色所示部分就是合格的剪取。

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

请填写表示方案数目的整数。

注意:

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

其实这个题目还是可前面的一样,先生成,再判断是否可行。

这里我们可以先用搜索从12个数里面将所有5个数的组合找出来。

然后再用深搜判断这五个是否连在一起。

答案是:

116

1.#include   

2.#include   

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\n",ans);  

88.    return 0;  

89.}  

第八题:

四平方和

四平方和定理,又称为拉格朗日定理:

每个正整数都可以表示为至多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

则程序应该输出:

0012

再例如,输入:

12

则程序应该输出:

0222

再例如,输入:

773535

则程序应该输出:

11267838

资源约定:

峰值内存消耗<256M

CPU消耗<3000ms

请严格按要求输出,不要画蛇添足地打印类似:

“请您输入...”的多余内容。

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

注意:

main函数需要返回0

注意:

只使用ANSIC/ANSIC++标准,不要调用依赖于编译环境或操作系统的特殊函数。

注意:

所有依赖的函数必须明确地在源文件中#include,不能通过工程设置而省略常用头文件。

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

这个题目很水也是搜索能做的。

但是有点技巧,这里我贡献两个方法给大家参考。

方法一:

O(n^3/2).先暴力枚举前三个数然后做减法判断差是否为一个完全平方数即可。

当然虽然这个题目是n^3/2看数据貌似过不了。

但是貌似我找了几组数据都能秒出结果。

应该是绝大多数最外层循环都不会太多。

1.#include   

2.#incl

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 理学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1