2011第二届蓝桥杯C/C++程序设计本科B组省赛试题解题报告

2012-2013跨年之作。

第一题

JC这个数组是0-9的阶乘,按照题目意思,我们需要对数进行分解,获得它的每一位。猜测循环条件是(x!=0)(x),重新阅读程序:对于每一个三位数判断,取出一位数,到JC中找出它的阶乘加到sum,将sum和自身比较,如果相等就输出。

那么,答案为(x!=0)(x)

第二题

很显然应该填j!=i。重新阅读程序:依次假定每一个数是最离群的数,算出平均值,计算去掉的数与平均数的距离,取最大值。

第三题

按递归思路看程序,循环体的第一条是递归边界控制语句,第二条到第四条是典型的交换语句,那么在这里完成的就是首尾对调。那么进一步调用自身,应该是调用原字符串去掉首尾后的子串。

那么答案就是reverse_str(buf+1,n-2)

第四题

这个按照十进制小数部分化其他进制看下去,非常通畅。首先乘上要化的进制(例如要化成二进制,就乘2),然后取出整数部分。

那么很容易推断出第一处是(int)dTestNo,第二处是iT[iNo]!=0iT[iNo]

第五题

从最后一句strcpy(s,s2)可以看出s2存放的是轮换后的结果,那么s2所需要的空间应该是(原字符串长度+1),那么第一处应该是sizeof(char)\(len+1)
再向下看,发现没有什么地方有写入s2的字符串终止符'\0',猜测第二处是'\0'。重新阅读程序:循环体内if语句实现的是,如果s2到达尾部,写入字符串终止符,并将下一个要写的位置设定为s2头部。

综上所述,第一处是sizeof(char)\(len+1),第二处是iT[iNo]!=0'\0'

第六题

首先,我就想到我们编程时惯用的手法,先保存它,然后修改它,最后还原它,那么第一处是sa[i+j]。接着,注意到返回值是n,那么n就应该是中了的数目。
纵观整个程序,n保存的应该是当前已知的最大数目,如果找到更大的就更新它,那么可以推测j就是当前的数目,那么第二处就是n=j

第七题

pro(m,n,x,y)是取x个球,至少y个。
m/(m+n)是本次抽到红球的概率,这种情况下,要满足至少y个,那么至少还需要抽到y-1个红球,第一处是pro(m-1,n,x-1,y-1)
n/(m+n)是本次抽到白球的概率,这种情况下,要满足至少y个,那么至少还需要抽到y个红球,第二处是pro(m,n-1,x-1,y)

第八题

建立一个矩阵,然后写入一个数后更新坐标,使他定位到下一个要写的位置。从最开始连续写入n个数开始,每次要连续写入的数都少了1个,也就是说连续写入的数分别 n n-1 n-2 …个。

可写顺序:向右 >> 向左下 >> 向上

那么在一个循环里,每次循环完成这三个步骤,注意控制好循环就行。

#include <stdio.h>
int main(void)
{

int i,j,n,s,x=0,y=0,num=1;
int bar[20][20]={{0}};
scanf("%d",&n);
s=n+1;
while(1)
{
--s;
if(s==0) break;
for(i=0; i<s; ++i)
{
bar[x][y] = num++;
if(i != s-1) ++y;
else
++x,--y;
}
--s;
if(s==0) break;
for(i=0; i<s; ++i)
{
bar[x][y] = num++;
if(i != s-1) ++x,--y;
else
--x;
}
--s;
if(s==0) break;
for(i=0; i<s; ++i)
{
bar[x][y] = num++;
if(i != s-1) --x;
else
++y;
}
}
for(i=0; i<n; ++i)
{
for(j=0; j<n-i; ++j)
printf("%4d",bar[i][j]);
printf("\n");
}
return 0;
}

第九题

因为没有更具体的数据范围,也没法详细讨论哪种算法好,直接暴力搜吧。

#include <iostream>
#include <string>
using namespace std;

#define MAX 10000

int N;
int m[MAX];
string res = "";
int s[MAX];

int count = 0;
void fun(int money, int cs){
if(money == 0) {
++count;
for(int i=0; i<N; ++i)
{
res += (char)('0' + s[i]) + string(" ");
}
res += "\n";
}
for(int i=cs; i < N; ++i)
{
int t = money - m[i];
if(t >= 0)
{
s[i]++;
fun(t, i);
s[i]--;
}
}
}

int main(void)
{

cin >> N;
for(int i=0; i<N; ++i) {
cin >> m[i];
}
fun(1000,0);
cout << count << endl;
cout << res << flush;
}

第十题

大模拟。

#include<stdio.h>
#include<string.h>
int main(void)
{

char abc[2][27] = {"abcdefghijklmnopqrstuvwxyz",{0}},temp[25];
char bar[5][5],key[26],str[51],res[51],a,b;
char *p;
int keylen,i,j,pos=0,abc_pos=0,x1,x2,y1,y2;
scanf("%s",key);
keylen = strlen(key);
for(i=0; i<keylen; ++i)
{
char t = key[i];
temp[pos++] = t;
abc[1][t-'a'] = 1;
}
while(1)
{
if(pos == 25) break;
if(abc[1][abc_pos] == 0) temp[pos++] = abc[0][abc_pos];
abc_pos++;
}
pos=0;
for(i=0; i<5; ++i)
for(j=0; j<5; ++j)
bar[i][j] = temp[pos++];
//密码表设置完成,开始获取加密数据并加密
scanf("%s",str);
pos = 0;
abc_pos = 0;
while(1)
{
if(str[abc_pos] != 0 && str[abc_pos+1] != 0)
{
a = str[abc_pos++];
b = str[abc_pos++];
}
else
break;
x1 = x2 = y1 = y2 = -1;
for(i=0; i<5; ++i)
for(j=0; j<5; ++j)
if(bar[i][j] == a)
x1 = i,y1 = j;
for(i=0; i<5; ++i)
for(j=0; j<5; ++j)
if(bar[i][j] == b)
x2 = i,y2 = j;
if(x1 == -1 || x2 == -1 || y1 == -1 || y2 == -1) //存在一个密码表中找不到的
{
res[pos++] = a;
res[pos++] = b;
}
else if(x1 == x2 || y1 == y2)//都在密码表中找到,但是同行或同列
{
res[pos++] = b;
res[pos++] = a;
}
else //都在密码表中找到,不同行或不同列
{
res[pos++] = bar[x1][y2];
res[pos++] = bar[x2][y1];
}
}
if(strlen(str)%2 == 1)
res[pos++] = str[strlen(str)-1];
res[pos] = 0;
printf("%s\n",res);
return 0;
}

下载