蓝桥杯模拟(本科)

本文地址:http://www.cnblogs.com/CheeseZH/archive/2012/04/06/2435134.html

2011 模拟 c语言 本科

注意:

本套模拟题主要模拟命题形式与考核范围。真实竞赛题的数量、难度可能与此套模拟题有差异。

说明:

本试卷包含两种题型:“代码填空”与“程序设计”。

填空题要求参赛选手在弄清给定代码工作原理的基础上填写缺失的部分,使得程序逻辑正确、完整。所填写的代码不多于一条语句(即不能出现分号)。

编程题要求选手设计的程序对于给定的输入能给出正确的输出结果。注意:在评卷时使用的输入数据与试卷中给出的实例数据可能是不同的。选手的程序必须是通用的,不能只对试卷中给定的数据有效。

 

1. 代码填空(满分2分)

下列代码,把一个2位整数交换十位与个位的位置。请填写缺失的代码。

例如:当x=95时,返回59

int switch_num(int x)
{
    int a = x / 10;
    int b = x % 10;
    return b*10+a;
}


 

2. 代码填空(满分3分)

下列代码把一个二进制的串转换为整数。请填写缺少的语句;

复制代码
1     char* p = "1010110001100";
2         int n = 0;
3         for(int i=0;i<strlen(p); i++)
4         {
5             n = n*2+p[i]-48;
6         }
7         printf("%d\n", n);
复制代码

 

3. 代码填空(满分3分)

假设a,b,c3个互不相等的整数。下列代码取出它们中居中的数值,记录在m中。其中的swap()函数可以交换两个变量的值。请完善代码。

1 if(a>b) swap(&a, &b);
2 if(b>c) swap(&b, &c);
3 if(a>b) swap(&a, &b);
4 int m = b;

4. 代码填空(满分5分)

计算3A2B可以组成多少种排列的问题(如:AAABB, AABBA)是《组合数学》的研究领域。但有些情况下,也可以利用计算机计算速度快的特点通过巧妙的推理来解决问题。下列的程序计算了mAnB可以组合成多少个不同排列的问题。请完善它。

int f(int m, int n)
{
    if(m==0 || n==0) return 1;
    return f(m,n-1)+f(m-1,n);
}

5. 代码填空(满分6分)

此段代码的意图是把一个缓冲区中的整数重新排列,使得所有负数都在正数的左边。请分析其工作流程,补充缺失的代码。

复制代码
 1 void reorder(int *pData, int len)
 2 {
 3       if(pData == NULL || len == 0) return;
 4       int *pBegin = pData;
 5       int *pEnd = pData+len-1;
 6       while(pBegin < pEnd)
 7       {
 8             if(*pBegin<0)
 9             {
10                   pBegin ++;
11                   continue;
12             }
13             if(*pEnd>=0)
14             {
15                   pEnd --;
16                   continue;
17             }
18 
19             int temp = *pBegin;
20             *pBegin = *pEnd;
21             *pEnd = temp;
22       }
23 }
24 
25 int main(int argc, char **argv)
26 {
27     int a[] = {1,2,3,-5,-4,5,9,-8,-1};
28     reorder(a, 9);
29 
30     for(int i=0; i<9; i++) printf("%d ", a[i]);
31     printf("\n");
32     return 0;   
33 }
复制代码

6. 代码填空(满分9分)

给定一个字符串,其含有的字符各不相同。程序输出该字符串的所有排列(全排列)情形。例如:给定字符串“xyz”,则程序输出:

xyz

xzy

yxz

yzx

zyx

zxy

试完善程序中空缺的部分。

复制代码
 1 void f(char *str, int len, int n)
 2 {   
 3     int i;   
 4     char tmp;   
 5     char *p = (char *)malloc(len+1);   
 6     if(n==len-1){   
 7         printf("%s\n",str);   
 8     }else{   
 9         for(i=n;i<len;i++){   
10             strcpy(p,str);   
11 
12             tmp = *(str+n);   
13             *(str+n) = *(str+i);   
14             *(str+i) = tmp;   
15 
16             f(str,len,n+1);      
17             strcpy(str,p);   
18         }   
19     }   
20     free(p);   
21 }   
22 
23 int main(int argc, char **argv)
24 {   
25     char str[] = "xyz";   
26     f(str,3,0);   
27     printf("\n");   
28     return 0;   
29 }
复制代码

7. 代码设计(满分5分)

625这个数字很特别,625的平方等于390625,刚好其末3位是625本身。除了625,还有其它的3位数有这个特征吗?

请编写程序,寻找所有这样的3位数:它的平方的末3位是这个数字本身。

输出结果中,从小到大,每个找到的数字占一行。比如那个625就输出为:

625

复制代码
#include <stdio.h>
void main()
{
    long i;
    for (i=100;i<=999;i++)    
        if (i*i%1000 == i)    
            printf("%ld\n",i);
}
复制代码

8. 代码设计(满分11分)

某游戏规则中,甲乙双方每个回合的战斗总是有一方胜利,一方失败。游戏规定:失败的一方要把自己的体力值的1/4加给胜利的一方。例如:如果双方体力值当前都是4,则经过一轮战斗后,双方的体力值会变为:53

现在已知:双方开始时的体力值甲:1000,乙:2000

假设战斗中,甲乙获胜的概率都是50%

求解:双方经过4个回合的战斗,体力值之差小于1000的理论概率。

复制代码
 1 #include <stdio.h>
 2 #include <math.h>
 3 int sum,r;
 4 void f(int n,int a,int b)
 5 {
 6     if (n==0)//四局比完
 7     {
 8         if (abs(a-b)<1000)
 9             r++;//符合条件的情况
10         sum++;//总的情况
11         return;
12     }
13     //a胜利
14     f(n-1,a+(b>>2),b-(b>>2));
15     //b胜利
16     f(n-1,a-(a>>2),b+(a>>2));
17 }
18 void main()
19 {
20     f(4,1000,2000);
21     printf("%.1lf%%\n",100.0*r/sum);
22 }
复制代码

9. 代码设计(满分18分)

整数的分划问题。 

如,对于正整数n=6,可以分划为: 

5+1 

4+2, 4+1+1 

3+3, 3+2+1, 3+1+1+1 

2+2+2, 2+2+1+1, 2+1+1+1+1 

1+1+1+1+1+1+1 

现在的问题是,对于给定的正整数n,编写算法打印所有划分。

用户从键盘输入 (范围1~10

程序输出该整数的所有划分。

复制代码
 1     #include <stdio.h>
 2     int sln[11];
 3     int idx,N;
 4     void output()
 5     {
 6         int i;
 7         printf("%d",sln[0]);
 8         for (i=1;i<idx;i++)
 9         {
10             printf("+%d",sln[i]);
11         }
12         printf(",");
13     }
14     void f(int m,int n)
15     {
16         int i;
17         if (n<0 || m<n)
18             return;
19         if (n==0)//如果n=0,说明找完了。输出
20         {
21             output();
22             return;
23         }
24         //如果m>=n&&n>=1,就从1查找到n。
25         for (i=n;i>=1;i--)
26         {
27             //首先把n放进去,并判断是否降序
28             sln[idx++]=i;
29             if(idx>1 && sln[idx-1]>sln[idx-2])
30             {
31                 idx--;
32                 continue;
33             }
34             //再把n分解,n可以分解为1-n的数
35             f(m-i,m-i);
36             idx--;
37             if (m==N)
38                 printf("\b \n");
39         }
40     }
41     void main()
42     {
43         while (scanf("%d",&N)!=EOF)
44         {
45             idx = 0;
46             f(N,N);
47         }    
48     }
复制代码


10. 代码设计(满分20分)

一个N位的十进制正整数,如果它的每个位上的数字的N次方的和等于这个数本身,则称其为花朵数。

例如:

N=3时,153就满足条件,因为 1^3 + 5^3 + 3^3 = 153,这样的数字也被称为水仙花数(其中,“^”表示乘方,5^3表示53次方,也就是立方)。

N=4时,1634满足条件,因为 1^4 + 6^4 + 3^4 + 4^4 = 1634

N=5时,92727满足条件。

实际上,对N的每个取值,可能有多个数字满足条件。

 

程序的任务是:求N=21时,所有满足条件的花朵数。注意:这个整数有21位,它的各个位数字的21次方之和正好等于这个数本身。

如果满足条件的数字不只有一个,请从小到大输出所有符合条件的数字,每个数字占一行。因为这个数字很大,请注意解法时间上的可行性。要求程序在3分钟内运行完毕。

 

复制代码
  1     #include<stdio.h>
  2     #include <string.h>
  3     #include <time.h>
  4     #define N 100000//虚拟进制
  5     #define BN  5//exp21的容量需求
  6     int exp21[10][BN]={//0-9的21次方
  7         {00000,00000,00000,00000,00000},
  8         {00000,00000,00000,00000,    1},
  9         {00000,00000,00000,   20,97152},
 10         {00000,00000,    1, 4603,53203},
 11         {00000,00000,  439,80465,11104},
 12         {00000,00000,47683,71582, 3125},
 13         {00000,   21,93695, 6403,77856},
 14         {00000,  558,54586,40832,84007},
 15         {00000, 9223,37203,68547,75808},
 16         {00001, 9418,98913,15123,59209}
 17     };
 18     int cm[10];//0-9被选的次数
 19     int nm[10];//21位数中0-9出现的次数
 20     int sum[BN];//累加和
 21     int pass[1000][10];//已经出现过的
 22     int sum_pass;
 23     int check()//检查sum是否合法
 24     {
 25         if (sum[0]>9&&cm[0]!=21)    return 0;
 26         return 1;
 27     }
 28     void Add(int *a,int *b)//大数加法:a+=b
 29     {
 30         int i,carry=0;
 31         for (i=BN-1;i>=0;i--)
 32         {
 33             a[i]=a[i]+b[i]+carry;
 34             carry = 0;
 35             if (a[i]>=N)
 36             {
 37                 a[i]-=N;
 38                 carry = 1;
 39             }
 40         }
 41     }
 42     void Sub(int *a,int *b)//大数减法:a-=b
 43     {
 44         int i,borrow=0;
 45         for (i=BN-1;i>=0;i--)
 46         {
 47             a[i]=a[i]-b[i]+borrow;
 48             borrow = 0;
 49             if (a[i]<0)
 50             {
 51                 a[i]+=N;
 52                 borrow = -1;
 53             }
 54         }
 55     }
 56     int IsRight()//判断是否是花朵数
 57     {
 58         int i,j;
 59         memset(nm,0,sizeof(nm));
 60         for (i=0;i<BN;i++)//统计sum中0-9的个数
 61         {
 62             j=sum[i];
 63             while (j)
 64             {
 65                 nm[j%10]++;
 66                 j/=10;
 67             }
 68         }
 69         for (i=0;i<10;i++)
 70             if (cm[i]!=nm[i])
 71                 return 0;
 72         return 1;
 73     }
 74     void save()//将花朵数存储在pass数组中
 75     {
 76         int i;
 77         pass[sum_pass][0]=sum[0];
 78         for (i=1;i<BN;i++)
 79             pass[sum_pass][i]=sum[i];
 80         sum_pass++;
 81     }
 82     void sln(int n,int m)//用若干个m填充n个空
 83     {
 84         int i,j;
 85         if (n==0)
 86             return;
 87         if (m==0)
 88         {
 89             cm[0]+=n;
 90             if(IsRight())
 91                 save();
 92             cm[0]-=n;
 93             return;
 94         }
 95         for (i=n;i>=0;i--)//最多用n个,最少用0个
 96         {
 97             cm[m]+=i;
 98             for (j=0;j<i;j++)Add(sum,exp21[m]);//sum加上i个exp21[m]
 99             if (!check())//检查是否溢出
100             {
101                 cm[m]-=i;
102                 for (j=0;j<i;j++)Sub(sum,exp21[m]);//sum减去i个exp21[m]
103                 continue;
104             }
105             if(n==1&&IsRight())    save();
106             sln(n-i,m-1);//用若干m-1填补剩余的n-i个空
107             cm[m]-=i;
108             for (j=0;j<i;j++)Sub(sum,exp21[m]);//sum减去i个exp21[m]
109         }
110     }
111     void print()//输出结果、有点偷懒。。。
112     {
113         printf("%d%05d%05d%05d%05d\n",pass[1][0],pass[1][1],pass[1][2],pass[1][3],pass[1][4]);
114         printf("%d%05d%05d%05d%05d\n",pass[0][0],pass[0][1],pass[0][2],pass[0][3],pass[0][4]);
115     }
116     void main()
117     {
118         double b,e;
119         b = (double)clock();
120          sln(21,9);
121         print();
122         e = (double)clock();
123         printf("程序执行时间:%.4fs\n",(e-b)/1000);
124     }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值