蓝桥杯第5届预赛高职高专组C语言真题解析.docx
- 文档编号:10643732
- 上传时间:2023-02-22
- 格式:DOCX
- 页数:25
- 大小:60.76KB
蓝桥杯第5届预赛高职高专组C语言真题解析.docx
《蓝桥杯第5届预赛高职高专组C语言真题解析.docx》由会员分享,可在线阅读,更多相关《蓝桥杯第5届预赛高职高专组C语言真题解析.docx(25页珍藏版)》请在冰豆网上搜索。
蓝桥杯第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[
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 蓝桥杯第 预赛 高职 高专组 语言 题解