蓝桥杯第5届预赛高职高专组C语言真题解析.docx

上传人:b****8 文档编号:10643732 上传时间:2023-02-22 格式:DOCX 页数:25 大小:60.76KB
下载 相关 举报
蓝桥杯第5届预赛高职高专组C语言真题解析.docx_第1页
第1页 / 共25页
蓝桥杯第5届预赛高职高专组C语言真题解析.docx_第2页
第2页 / 共25页
蓝桥杯第5届预赛高职高专组C语言真题解析.docx_第3页
第3页 / 共25页
蓝桥杯第5届预赛高职高专组C语言真题解析.docx_第4页
第4页 / 共25页
蓝桥杯第5届预赛高职高专组C语言真题解析.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

蓝桥杯第5届预赛高职高专组C语言真题解析.docx

《蓝桥杯第5届预赛高职高专组C语言真题解析.docx》由会员分享,可在线阅读,更多相关《蓝桥杯第5届预赛高职高专组C语言真题解析.docx(25页珍藏版)》请在冰豆网上搜索。

蓝桥杯第5届预赛高职高专组C语言真题解析.docx

蓝桥杯第5届预赛高职高专组C语言真题解析

2014年蓝桥杯(第5届)预赛高职高专组真题解析

武功秘籍

小明到X山洞探险,捡到一本有破损的武功秘籍(2000多页!

当然是伪造的)。

他注意到:

书的第10页和第11页在同一张纸上,但第11页和第12页不在同一张纸上。

小明只想练习该书的第81页到第92页的武功,又不想带着整本书。

请问他至少要撕下多少张纸带走?

这是个整数,请通过浏览器提交该数字,不要填写任何多余的内容。

(1)答案。

7

(2)编程思路。

因为每页页码开始为偶数,终止为奇数,因此若开始页码为奇数或终止页码为偶数,则应多加1页。

(3)源程序。

#include

intmain()

{

intm,n,ans;

while(scanf("%d%d",&n,&m)!

=EOF)

{

ans=m-n+2;

ans/=2;

if(n%2!

=0&&m%2==0)

ans++;

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

}

return0;

}

等额本金

小明从银行贷款3万元。

约定分24个月,以等额本金方式还款。

这种还款方式就是把贷款额度等分到24个月。

每个月除了要还固定的本金外,还要还贷款余额在一个月中产生的利息。

假设月利率是:

0.005,即:

千分之五。

那么,

第一个月,小明要还本金1250,还要还利息:

30000*0.005,总计1400.00

第二个月,本金仍然要还1250,但利息为:

(30000-1250)*0.005总计1393.75

请问:

小明在第15个月,应该还款多少(本金和利息的总和)?

请把答案金额四舍五入后,保留两位小数。

注意:

32.5,一定要写为:

32.50

通过浏览器提交答案,这是一个含有小数点和两位小数的浮点数字。

不要写多余内容(例如:

多写了“元”或添加说明文字)

(1)答案。

1312.50

(2)编程思路。

简单循环计算。

(3)源程序。

#include

intmain()

{

doublen=30000;

intm=24;

for(inti=1;i<=m;i++)

{

printf("%d%.2f\n",i,1250+n*0.005);

n-=1250;

}

return0;

}

猜字母

把abcd...s共19个字母组成的序列重复拼接106次,得到长度为2014的串。

接下来删除第1个字母(即开头的字母a),以及第3个,第5个等所有奇数位置的字母。

得到的新串再进行删除奇数位置字母的动作。

如此下去,最后只剩下一个字母,请写出该字母。

答案是一个小写字母,请通过浏览器提交答案。

不要填写任何多余的内容。

(1)答案。

q

(2)编程思路。

用循环直接模拟删除字符的过程。

(3)源程序。

#include

intmain()

{

charstr[2015];

charsrc[20]="abcdefghijklmnopqrs";

intn,i,k;

for(n=1,k=0;n<=106;n++)

{

for(i=0;i<19;i++)

str[k++]=src[i];

}

str[k]=0;

intlen=k;

while(len>1)

{

for(k=0,i=0;str[i]!

='\0';i++)

if(i%2!

=0)str[k++]=str[i];

str[k]='\0';

len=k;

}

printf("%s\n",str);

return0;

}

大衍数列

中国古代文献中,曾记载过“大衍数列”,主要用于解释中国传统文化中的太极衍生原理。

它的前几项是:

0、2、4、8、12、18、24、32、40、50...

其规律是:

对偶数项,是序号平方再除2,奇数项,是序号平方减1再除2。

以下的代码打印出了大衍数列的前100项。

intmain()

{

inti;

for(i=1;i<100;i++){

if(__________________)//填空

printf("%d",i*i/2);

else

printf("%d",(i*i-1)/2);

}

printf("\n");

}

请填写划线部分缺失的代码。

通过浏览器提交答案。

注意:

不要填写题面已有的内容,也不要填写任何说明、解释文字。

(1)参考答案。

i%2==0

打印图形

小明在X星球的城堡中发现了如下图形和文字:

小明开动脑筋,编写了如下的程序,实现该图形的打印。

#defineN70

voidf(chara[][N],intrank,introw,intcol)

{

if(rank==1){

a[row][col]='*';

return;

}

intw=1;

inti;

for(i=0;i

____________________________________________;

f(a,rank-1,row+w/2,col);

f(a,rank-1,row+w/2,col+w);

}

intmain()

{

chara[N][N];

inti,j;

for(i=0;i

for(j=0;j

f(a,6,0,0);

for(i=0;i

for(j=0;j

printf("\n");

}

return0;

}

请仔细分析程序逻辑,填写缺失代码部分。

(1)参考答案。

f(a,rank-1,row,col+w/2);

神奇算式

由4个不同的数字,组成的一个乘法算式,它们的乘积仍然由这4个数字组成。

比如:

210x6=1260

8x473=3784

27x81=2187

都符合要求。

如果满足乘法交换律的算式算作同一种情况,那么,包含上边已列出的3种情况,一共有多少种满足要求的算式。

请填写该数字,通过浏览器提交答案,不要填写多余内容(例如:

列出所有算式)。

(1)正确答案。

12

(2)编程思路。

采用穷举法来解决。

穷举对象分别为积和那个较小的乘数。

其中积是一个4位数,取值范围为1023~9876,乘数的取值范围为2~98。

循环体中需要检测两个约束条件:

1)积这个4位数中每一位数字不允许重复;2)这4个数字出现且仅出现2次。

这些约束条件可使用一个标记数组used[10]来处理。

used数组的初值全为0,当数字i使用后,置used[i]=1,若数字i再次使用时,此时used[i]又等于1,则可判定约束条件不满足。

(3)源程序。

#include

intcheck(intx,inty,intused[10])

{

inti,tmp[10]={0};

do{

tmp[x%10]++;

}while(x/=10);

do{

tmp[y%10]++;

}while(y/=10);

for(i=0;i<10;i++)

if(tmp[i]!

=used[i])

return0;

return1;

}

intcheck4(intx,intused[10])

{

do{

if(used[x%10]!

=0)

return0;

used[x%10]++;

}while(x/=10);

return1;

}

intmain()

{

inta,b,c,i,cnt=0,used[10];

for(c=1023;c<=9876;c++)

{

for(i=0;i<10;i++)

used[i]=0;

if(!

check4(c,used))

continue;

for(a=2;a<=98;a++)

{

if(c%a!

=0)

continue;

b=c/a;

if(a>b)

continue;

if(!

check(a,b,used))

continue;

printf("%d*%d=%d\n",a,b,c);

cnt++;

}

}

printf("Count=%d\n",cnt);

return0;

}

绳圈

今有100根绳子,当然会有200个绳头。

如果任意取绳头两两配对,把所有绳头都打结连接起来。

最后会形成若干个绳圈(不考虑是否套在一起)。

我们的问题是:

请计算最后将形成多少个绳圈的概率最大?

注意:

结果是一个整数,请通过浏览器提交该数字。

不要填写多余的内容。

(1)答案。

3

(2)编程思路。

设dp[i][j]表示i条绳结成j个圈的概率,c[i]表示i条绳的2i个端点配对的种数,有c[1]=1,c[i]=c[i-1]*(2i-1),

由于i条绳结成i个圈只有一种可能,即每条绳自己组成一个圈,故

有dp[i][i]=1/c[i]

进一步,i条绳结成j(2<=j

1)第i条绳跟自己组合成圈,其余i-1条绳组成j-1个圈;2)第i条绳与其他绳子的绳头组合,可将它与某条绳两个绳头结在一起后看成1条绳,这样i-1条绳构成j个圈。

顾有

dp[i][j]=(dp[i-1][j]*c[i-1]*(i-1)*2+dp[i-1][j-1]*c[i-1])/c[i]

再根据c[i]和c[i-1]的递推关系将c[i]和c[i-1]约去,得到递推式

dp[i][j]=(dp[i-1][j]*(2*i-2)+dp[i-1][j-1])/(2*i-1);

(3)源程序。

#include

intmain()

{

doubledp[101][101]={0};

dp[1][1]=1;

inti,j;

for(i=2;i<=100;i++)

{

for(j=1;j<=i;j++)

{

dp[i][j]=dp[i-1][j-1]/(2*i-1)+dp[i-1][j]*(2*i-2)/(2*i-1);

}

}

intans=0;

doublemaxR=0;

for(i=1;i<=100;i++)

{

if(dp[100][i]>maxR)

{

ans=i;

maxR=dp[100][i];

}

}

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

return0;

}

分糖果

有n个小朋友围坐成一圈。

老师给每个小朋友随机发偶数个糖果,然后进行下面的游戏:

每个小朋友都把自己的糖果分一半给左手边的孩子。

一轮分糖后,拥有奇数颗糖的孩子由老师补给1个糖果,从而变成偶数。

反复进行这个游戏,直到所有小朋友的糖果数都相同为止。

你的任务是预测在已知的初始糖果情形下,老师一共需要补发多少个糖果。

【格式要求】

程序首先读入一个整数N(2

接着是一行用空格分开的N个偶数(每个偶数不大于1000,不小于2)

要求程序输出一个整数,表示老师需要补发的糖果数。

例如:

输入

3

224

程序应该输出:

4

(1)编程思路。

我们用逐步求精的方法来分析这个问题的解决方法。

1)先写出程序的总体框架如下:

输入n个小孩的初始糖果数①;

While(n个小孩的糖果数不全相等②)

{

所有小孩同时把自己糖果的一半分给左边的小孩③;

糖的块数为奇数的小孩向老师补要一块,且补发颗数加1④;

}

输出结果信息

在这个总体框架中需要解决4个问题。

2)设定义一个整型数组a来保存10个小孩的糖果数,问题①就是需要输入n个数组元素的初始值,程序代码为:

for(i=0;i

scanf(“%d”,&a[i]);

3)问题②需要判断n个小孩的糖果数是否相等,显然是一个操作序列,其判断结果是while循环的条件,因此将问题②抽象成一个函数AllEqual,该函数用来判断数组中所有元素的值是否都相等,如果都相等则返回1,否则返回0。

其函数原型为:

intAllEqual(intx[]);

而为判断一个数组中所有元素的值是否全相等,最简单的办法为将数组中的第2个数至最后一个数与第1个数相比较,只要它们中有一个不相等,就返回0(不全相等),如果比较完后,没有返回0,则它们全相等,返回1。

函数的定义为:

intAllEqual(intx[],intn)

{

inti;

for(i=1;i

if(x[i]!

=x[0])return0;

return1;

}

4)问题③完成一次调整过程,所有小孩需要同时把自己糖果的一半分给左边的小孩,如下图所示。

图1一次调整过程示例图

由图看出(以n=10为例),

当i=1~9时,有a(i)=(a(i)+a(i-1))/2

i=0时,a(0)=(a(0)+a(9))/2

因此,很容易地想到可以写成如下的代码段:

a[0]=a[0]/2+a[n-1]/2;

for(i=1;i

a[i]=a[i]/2+a[i-1]/2;

这样写是错误的,为什么呢?

因为先修改a[1],当计算a[2]时,用到的a[1]已经被修改了。

应该写成:

temp=a[n-1];

for(i=n-1;i>0;i--)

a[i]=a[i]/2+a[i-1]/2;

a[0]=a[0]/2+temp/2;

5)问题④可以用一个循环程序解决,对数组中的每个元素判断其奇偶性,如果为奇数,则将该元素值加1。

程序代码为:

for(i=0;i

if(a[i]%2!

=0){a[i]++;ans++;}

至此,可以写出完整的源程序。

(2)源程序。

#include

intAllEqual(intx[],intn)

{

inti;

for(i=1;i

if(x[i]!

=x[0])return0;

return1;

}

intmain()

{

intn,i,ans=0;

inta[100];

scanf("%d",&n);

for(i=0;i

scanf("%d",&a[i]);

while(AllEqual(a,n)!

=1)

{

inttemp;

temp=a[n-1];

for(i=n-1;i>0;i--)

a[i]=a[i]/2+a[i-1]/2;

a[0]=a[0]/2+temp/2;

for(i=0;i

if(a[i]%2!

=0)

{

a[i]++;ans++;

}

}

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

return0;

}

地宫取宝

X国王有一个地宫宝库。

是nxm个格子的矩阵。

每个格子放一件宝贝。

每个宝贝贴着价值标签。

地宫的入口在左上角,出口在右下角。

小明被带到地宫的入口,国王要求他只能向右或向下行走。

走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。

当小明走到出口时,如果他手中的宝贝恰好是k件,则这些宝贝就可以送给小明。

请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这k件宝贝。

【数据格式】

输入一行3个整数,用空格分开:

nmk(1<=n,m<=50,1<=k<=12)

接下来有n行数据,每行有m个整数Ci(0<=Ci<=12)代表这个格子上的宝物的价值

要求输出一个整数,表示正好取k个宝贝的行动方案数。

该数字可能很大,输出它对1000000007取模的结果。

例如,输入:

222

12

21

程序应该输出:

2

再例如,输入:

232

123

215

程序应该输出:

14

(1)编程思路。

采用记忆化搜索完成。

定义4维数组dp[51][51][15][15]。

设dp[x][y][num][val]表示在坐标(x,y)时拿了num件宝贝并且宝贝中价值最大的为val,其中1≤x≤n,1≤y≤m,num的初值为0,表示还没有拿到宝贝,val的初值本来应该为-1,表示此时手上还没有宝物(因为从题目数据说明中可以看出宝贝的价值可以为0),为了让val初始值为0,可以将输入的宝贝的价值统一加1,这样宝贝的最小价值为1(不是0)。

定义二维数组intmap[51][51]保存地宫各格子的宝贝价值。

采用倒推法列出状态转移方程,即把后面的情况种数不断的往前更新。

当map[x][y]>val时,

dp[x][y][num][val]=dp[x+1][y][num+1][map[x][y]]+dp[x][y+1][num+1][map[x][y]]

+dp[x+1][y][num][val]+dp[x][y+1][num][val];

当map[x][y]<=val时,

dp[x][y][num][val]=dp[x+1][y][num][val]+dp[x][y+1][num][val]。

在通过DFS搜索方式求数组dp的各元素值时,由于数组元素值dp[x][y][num][val]跟位置(x,y)、宝贝个数以及当前最大的宝贝价值有关,当重复遍历这个结点时,若dp[x][y][num][val]的值已经计算出来了,则直接应用无需重复递归计算。

为此,定义数组dp的全部元素的初始值为-1。

若计算时需要用到dp[x][y][num][val],此时dp[x][y][num][val]!

=-1,则无需重复调用,直接应用计算好的dp[x][y][num][val]元素值。

之所以初值定义为-1,是考虑到若路径不存在的情况(此时方案数应为0)。

(2)源程序。

#include

#include

#defineMOD1000000007

longlongdp[51][51][15][15];

intmap[51][51];

intn,m,k;

voiddfs(intx,inty,intnum,intval)

{

if(dp[x][y][num][val]!

=-1)

return;

dp[x][y][num][val]=0;

if(x==n&&y==m&&num==k)

{

dp[x][y][num][val]=1;

return;

}

if(map[x][y]>val&&num

{

dfs(x,y,num+1,map[x][y]);

dp[x][y][num][val]+=dp[x][y][num+1][map[x][y]];

dp[x][y][num][val]%=MOD;

}

if(x

{

dfs(x+1,y,num,val);

dp[x][y][num][val]+=dp[x+1][y][num][val];

dp[x][y][num][val]%=MOD;

}

if(y

{

dfs(x,y+1,num,val);

dp[x][y][num][val]+=dp[x][y+1][num][val];

dp[x][y][num][val]%=MOD;

}

}

intmain()

{

scanf("%d%d%d",&n,&m,&k);

for(inti=1;i<=n;i++)

{

for(intj=1;j<=m;j++)

{

scanf("%d",&map[i][j]);

map[i][j]++;

}

}

memset(dp,-1,sizeof(dp));

dfs(1,1,0,0);

printf("%d\n",dp[1][1][0][0]);

return0;

}

小朋友排队

n个小朋友站成一排。

现在要把他们按身高从低到高的顺序排列,但是每次只能交换位置相邻的两个小朋友。

每个小朋友都有一个不高兴的程度。

开始的时候,所有小朋友的不高兴程度都是0。

如果某个小朋友第一次被要求交换,则他的不高兴程度增加1,如果第二次要求他交换,则他的不高兴程度增加2(即不高兴程度为3),依次类推。

当要求某个小朋友第k次交换时,他的不高兴程度增加k。

请问,要让所有小朋友按从低到高排队,他们的不高兴程度之和最小是多少。

如果有两个小朋友身高一样,则他们谁站在谁前面是没有关系的。

【数据格式】

输入的第一行包含一个整数n,表示小朋友的个数。

第二行包含n个整数H1H2…Hn,分别表示每个小朋友的身高。

输出一行,包含一个整数,表示小朋友的不高兴程度和的最小值。

例如,输入:

3

321

程序应该输出:

9

【样例说明】

首先交换身高为3和2的小朋友,再交换身高为3和1的小朋友,再交换身高为2和1的小朋友,每个小朋友的不高兴程度都是3,总和为9。

【数据规模与约定】

对于10%的数据,1<=n<=10;

对于30%的数据,1<=n<=1000;

对于50%的数据,1<=n<=10000;

对于100%的数据,1<=n<=100000,0<=Hi<=1000000。

(1)编程思路。

本题的实质是求一组数据中逆序数对的个数。

比如题目中的3,2,1,和3有关的逆序对为(3,2)和(3,1),和2有关的逆序对为(3,2)和(2,1),和1有关的逆序对为(3,1)和(2,1),为了完成排序,任何一个逆序对的两个元素都必须交换一次,于是可知,每个小朋友都完成了两次交换。

要求一个数组元素有关的逆序对个数,就是求它之前有几个大于它的元素(设为b1),之后有几个小于它的元素(设为b2),这样每个元素相关的逆序数对个数(也是需交换次数)为b1+b2。

根据数据规模与约定,若采用二重循环进行暴力搜索逆序对的个数,肯定会超时的。

因此,采用树状数组来解决本题。

树状数组实际上是由两部分组成:

数据数组(设为num)和统计数组(设为C)。

我们以数据数组num[

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

当前位置:首页 > 经管营销 > 公共行政管理

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

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