第三届蓝桥杯复赛题解析

第三届蓝桥杯复赛题原题:

http://www.cnblogs.com/AkQuan/archive/2012/04/10/2440370.html

第一题:

 1 #include <cstdio> 
 2 int main() 
 3 { 
 4   long int X=10, Y=90; 
 5   for(int k=1; k<=120; k++)//半分钟一个单位 
 6   { 
 7     if(k%2==1)Y -= X;//因为X出生半分钟后就要吃Y,尔后每1分钟要吃Y,所以永远都是奇数个半分钟的时候吃Y,又因为此时X不会增长(题目为了减小讨论的复杂度),所以直接减X数量即可。 
 8     if(k%4==0)Y *= 2;//每2分钟翻倍 
 9     if(k%6==0)X *= 2;//每3分钟翻倍,X和Y的翻倍是相互独立的,不需要另作讨论。 
10    } 
11   printf("%d", Y); 
12return 0; 
13 }

 

第二题

这里推荐用一层循环,代码少一点,由于a*b=c(a/b/c都是正整数)可以得出c能被a整除,我们可以类似求回文数一样求出c,然后判断c%a==0是否成立即可,但是这里要注意判重,即a(五位数)的各个数字互不想同。

 1 #include <cstdio> 
 2  
 3 int main() 
 4 { 
 5     int a, b, num[5]; 
 6     for(a = 10000; a < 100000; a++) 
 7     { 
 8         int t = a, base = 10000, k = 0; 
 9         b = 0; 
10         while(t) 
11         { 
12             num[k] = t % 10; 
13             b = b * 10 + num[k]; 
14             for(int i = 0; i < k; i++) 
15             { 
16                 if(num[k] == num[i]) break; 
17             } 
18             if(i != k) break; 
19             k++; 
20             t /= 10; 
21         } 
22         if(!t && b % a == 0)printf("%d\n", a); 
23     } 
24     return 0; 
25 } 
26  

 

第三题

这里推荐一种更为普遍的方法:(dfs)

 1 #include <cstdio> 
 2 #define MAX 20 
 3  
 4 int n, m;        //n个海盗,m轮后全体倒下,船长喝了t瓶酒 
 5 double drink[MAX], t;    //记录船长每轮喝的酒量 
 6  
 7 void dfs(int x, int y) 
 8 { 
 9     if(y <= 0) 
10     { 
11         double sum = 0.0; 
12         for(int i = 1; i <= m; i++) 
13             sum += drink[i]; 
14         double dif = sum - t; 
15         if(dif < 0.0) dif = -dif; 
16         if(dif < 0.000001) 
17         { 
18             for(int i = m; i > 0; i--) 
19                 printf("%d ", (int)(1.0 / drink[i])); 
20             printf("\n"); 
21         } 
22         return; 
23     } 
24     if(x <= 0) return; 
25  
26     drink[y] = 1.0 / x; 
27     for(int i = 1; i < x; i++) 
28         dfs(x - i, y - 1); 
29 } 
30  
31 int main() 
32 { 
33     m = 4;        //喝了四轮 
34     t = 1.0;    //船长喝了一瓶酒 
35     for(n = 20; n >= 1; n--) 
36         dfs(n, m); 
37     return 0; 
38 } 

 

第四题

用位运算枚举,可以更加方便快捷。

 1 #include <cstdio> 
 2  
 3 int main() 
 4 { 
 5     char str[11]; 
 6     for(long i = 0; i < (1 << 10); i++) 
 7     { 
 8         int fen = 10; 
 9         for(int j = 0; j < 10; j++) 
10         { 
11             str[j] = ((i >> j) & 1) + '0'; 
12             if(str[j] - '0') fen *= 2; 
13             else fen -= j + 1; 
14         } 
15         str[j] = 0; 
16         if(100 == fen) 
17             puts(str); 
18     } 
19     return 0; 
20 } 

 

第五题

代码略

参考答案:

sizeof(int)*rank*rank
rank*(i%rank) + rank-i/rank-1

 

第六题

代码略

参考答案:

n3/base+n2/base+n4%base
r[2]/base

 

第七题

代码略

参考答案:

NumRow!=3 || NumCol!=3
f(x,r,c+1)
x[r][c]==1

 

第八题

此题有一个技巧,原题的算法:228 => 2+2+8 => 12 => 1+2 => 3

其实只需要 228 => 228%9 => 3 即可,若余数为 0,则直接取 9 。

 1 #include <cstdio> 
 2 #include <cstring> 
 3 #define MAX 1005 
 4  
 5 long num[6]; 
 6 char tmp[MAX]; 
 7  
 8 int main() 
 9 { 
10     int t; 
11     scanf("%d", &t); 
12     while(t) 
13     { 
14         memset(num, 0, sizeof num); 
15         fgets(tmp, MAX, stdin); 
16         if(tmp[0] == '\n' || strlen(tmp) == 0) continue; 
17  
18         for(int i = 0; tmp[i] != 0 && tmp[i] != '\n'; i++) 
19         { 
20             num[i%6] += tmp[i]; 
21         } 
22  
23         for(int j = 0; j < 6; j++) 
24         { 
25             int t = num[j] % 9; 
26             printf("%d", t ? t : 9); 
27         } 
28         putchar('\n'); 
29         --t; 
30     } 
31     return 0; 
32 } 

 

 

第九题

思路:

p = 1 - 甲输的概率

甲输的话,有两种情况:
1:甲在第一轮中就输了
2:甲在晋级后,决赛中输了

假设 甲 先和 X 对决,则另两组是 Y 和 Z 对决
其中 Y 和 Z 对决有两种情况发生:要么Y赢,要么Z赢
所以综合上述讨论,可以算出甲输的概率是:

P(X, 甲) + P(甲,X)*P(Y, Z)*P(Y, 甲) + P(甲,X)*P(Z, Y)*P(Z, 甲)

即甲赢的概率是 1 减去上诉结果。
10万数据模拟可以得到甲赢的概率大约0.076。
验算:甲换成乙丙丁后分别算出四个数据,相加为1.0

 

 1 #include <cstdio> 
 2 #include <stdlib.h> 
 3 #include <time.h> 
 4 #define COUNT 100000 
 5  
 6 const int g = 0; 
 7  
 8 double P[4][4] = {{0, 0.1, 0.3, 0.5}, 
 9     {0.9, 0, 0.7, 0.4}, 
10     {0.7, 0.3, 0, 0.2}, 
11     {0.5, 0.6, 0.8, 0} 
12 }; 
13  
14  
15 int main() 
16 { 
17     srand((unsigned)time(NULL)); 
18     double sum = 0.0; 
19  
20     for(int k = 1; k <= COUNT; k++) 
21     { 
22         int x = g, y = g, z = g; 
23         while(x == g) x = rand() % 4; 
24         //while(y==g || y==x) y=rand()%4;        //此处的生成y的方法和下面的方法有轻微差异 
25         for(int ii = 0; ii < 4 && (ii == g || ii == x); )++ii; //约有0.001的浮动,推荐用下面这个方法 
26         y = ii; 
27         for(int i = 0; i < 4 && (i == g || i == x || i == y); )++i; 
28         z = i; 
29         double r = 1 - (P[x][g] + P[g][x] * (P[y][z] * P[y][g] + P[z][y] * P[z][g])); 
30         sum += r; 
31     } 
32     printf("%lf\n", sum / COUNT); 
33  
34     return 0; 
35 } 

 

 

第十题

博弈问题,递推或者DP都可以解决,这里用递推。

 1 #include <stdio.h> 
 2 #include <string.h> 
 3 int a[10001]; 
 4 int b[4] = {1, 3, 7, 8}; 
 5 int main() 
 6 { 
 7     int i, n, j; 
 8 
 9     memset(a, 0, sizeof a);     //初始化判定数组为0 
10     a[0] = 1;                 //说明对方取完了最后一堆,那么自己胜利 
11     for(i = 1; i <= 10000; i++) 
12         for(j = 0; j < 4; j++)if(i - b[j] >= 0) 
13             { 
14                 if(a[i-b[j]] == 0)     //有取法能致使对方输,那么自己就要赢 
15                 { 
16                     a[i] = 1; 
17                     break; 
18                 } 
19             } 
20 
21     scanf("%d", &n); 
22     while(n--) 
23     { 
24         scanf("%d", &i); 
25         printf("%d\n", a[i]); 
26     } 
27     return 0; 
28 } 
29  

 

posted @ 2012-04-10 15:16  Muse牧马  Views(875)  Comments(0Edit  收藏  举报