清华大学 2006年机试题

题目1076:N的阶乘

题目描述:

 输入一个正整数N,输出N的阶乘。

输入:

正整数N(0<=N<=1000)

输出:

 输入可能包括多组数据,对于每一组输入数据,输出N的阶乘

样例输入:
4
5
15
样例输出:
24
120
1307674368000

该题考察长整数乘法
开始的代码是这样的
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <string>
 5 #define MAX 3002
 6 int ans[MAX];
 7 int len;
 8 int ans2[MAX];
 9  
10 void cal(int m) {
11     int ci = 0;
12     int q;
13     int pm = -1;
14     int len2 = len;
15     memset(ans2,0,sizeof(ans2));
16     while(m != 0) {
17         int tempM = m % 10;
18         pm++;
19         q = pm;
20         for(int i = 0; i < len; i++) {
21             int tempSum = ans[i] * tempM  + ci + ans2[q];
22             int tempBen = (tempSum) % 10;
23             ci = (tempSum) / 10;
24             ans2[q] = tempBen;
25             q++;
26         }
27         while(ci != 0) {
28             int bt = ci % 10;
29             ans2[q] = ans2[q] + bt;
30             q++;
31             ci = ci/10;
32         }
33         len2 = q;
34         m = m/10;
35     }
36     for(int i = 0; i < len2; i++) {
37         ans[i] = ans2[i];
38     }
39     len = len2;
40 }
41  
42 void show() {
43     for(int i = len-1; i >= 0; i--) {
44         printf("%d",ans[i]);
45     }
46     printf("
");
47 }
48  
49 int main(int argc, char const *argv[])
50  {
51     int n;
52     while(scanf("%d",&n) != EOF) {
53         if(n == 0 || n == 1) {
54             puts("1");
55             continue;
56         }
57         memset(ans,0,sizeof(ans));
58         ans[0] = 1;
59         len = 1;
60         for(int i = 2; i <= n; i++) {
61             cal(i);
62         }
63         show();
64     }
65     return 0;
66  } 

可是超时了,观察到题目所要求的内存范围比较大,修改为如下代码:

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <string>
 5 #define MAX 3002
 6  
 7  
 8 int ansn[1002][MAX];
 9 int lenn[1002];
10  
11 void cal2(int m) {
12     int ci = 0;
13     int q;
14     int pm = -1;
15     memset(&ansn[m],0,sizeof(&ansn[m]));
16     int mo = m;
17     while(mo != 0) {
18         int tempM = mo % 10;
19         pm++;
20         q = pm;
21         for(int i = 0; i < lenn[m-1]; i++) {
22             int tempSum = ansn[m-1][i] * tempM  + ci + ansn[m][q];
23             int tempBen = (tempSum) % 10;
24             ci = (tempSum) / 10;
25             ansn[m][q] = tempBen;
26             q++;
27         }
28         while(ci != 0) {
29             int bt = ci % 10;
30             ansn[m][q] = ansn[m][q] + bt;
31             q++;
32             ci = ci/10;
33         }
34         lenn[m] = q;
35         mo = mo/10;
36     }
37  
38 }
39  
40  
41 void show(int m) {
42     for(int i = lenn[m]-1; i >= 0; i--) {
43         printf("%d",ansn[m][i]);
44     }
45     printf("
");
46 }
47  
48 int main(int argc, char const *argv[])
49  {
50     int n;
51     memset(&ansn[1],0,sizeof(&ansn[1]));
52     ansn[1][0] = 1;
53     lenn[1] = 1;
54     for(int i = 2; i <= 1000; i++) {
55         cal2(i);
56     }
57     while(scanf("%d",&n) != EOF) {
58         if(n == 0 || n == 1) {
59             puts("1");
60             continue;
61         }
62          
63         show(n);
64     }
65     return 0;
66  } 

提交成功,但内存几乎要达到上限

下面做出如下改进,首先,计算乘法时不需要把m的每一位都拆出来再乘,可以直接乘m,对结果不影响,修改为如下代码

其次,存储时也没必要每一位用一个int来存,一个int完全可以存多位,以此减少内存消耗

代码如下

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <string>
 5 #define MAX 502
 6 #define BASE 1000000
 7  
 8 int ansn[1002][MAX];
 9 int lenn[1002];
10  
11 void cal2(int m) {
12     int ci = 0;
13     memset(&ansn[m],0,sizeof(&ansn[m]));
14      
15     int q = 0;
16     for(int i = 0; i < lenn[m-1]; i++) {
17         int tempSum = ansn[m-1][i] * m  + ci ;
18         int tempBen = (tempSum) % BASE;
19         ci = (tempSum) / BASE;
20         ansn[m][q] = tempBen;
21         q++;
22     }
23     while(ci != 0) {
24         int bt = ci % BASE;
25         ansn[m][q] = bt;
26         q++;
27         ci = ci/BASE;
28     }   
29     lenn[m] = q;
30 }
31  
32  
33 void show(int m) {
34     printf("%d",ansn[m][lenn[m]-1]);
35     for(int i = lenn[m]-2; i >= 0; i--) {
36         printf("%06d",ansn[m][i]);
37     }
38     printf("
");
39 }
40  
41 int main(int argc, char const *argv[])
42  {
43     int n;
44     memset(&ansn[1],0,sizeof(&ansn[1]));
45     ansn[1][0] = 1;
46     lenn[1] = 1;
47     for(int i = 2; i <= 1000; i++) {
48         cal2(i);
49     }
50     while(scanf("%d",&n) != EOF) {
51         if(n == 0 || n == 1) {
52             puts("1");
53             continue;
54         }
55          
56         show(n);
57     }
58     return 0;
59  } 

题目1077:最大序列和

题目描述:

给出一个整数序列S,其中有N个数,定义其中一个非空连续子序列T中所有数的和为T的“序列和”。
对于S的所有非空连续子序列T,求最大的序列和。
变量条件:N为正整数,N≤1000000,结果序列和在范围(-2^63,2^63-1)以内。
 

输入:

第一行为一个正整数N,第二行为N个整数,表示序列中的数。

输出:

输入可能包括多组数据,对于每一组输入数据,
仅输出一个数,表示最大序列和。

样例输入:
5
1 5 -3 2 4

6
1 -2 3 4 -10 6

4
-3 -1 -2 -5
样例输出:
9
7
-1

这是一道经典题,代码如下
 1 #include <cstdio>
 2 #include <cstdlib>
 3 int main(int argc, char const *argv[])
 4  {
 5     long long int n;
 6  
 7     while(scanf("%lld",&n) != EOF) {
 8         long long int max;
 9         long long int sum;
10         long long int temp;
11  
12         scanf("%lld",&temp);
13         max = temp;
14         sum = temp;
15  
16         if(sum < 0) {
17             sum = 0;
18         }
19  
20         for(long long int i = 1; i < n; i++) {
21             scanf("%lld",&temp);
22             sum = sum + temp;
23              
24             if(max < sum) {
25                 max = sum;
26             }
27  
28             if(sum < 0) {
29                 sum = 0;
30             }
31         }
32  
33         printf("%lld
", max);
34     }
35     return 0;
36  } 

题目1078:二叉树遍历

题目描述:

二叉树的前序、中序、后序遍历的定义:
前序遍历:对任一子树,先访问跟,然后遍历其左子树,最后遍历其右子树;
中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树;
后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。
给定一棵二叉树的前序遍历和中序遍历,求其后序遍历(提示:给定前序遍历与中序遍历能够唯一确定后序遍历)。

输入:

两个字符串,其长度n均小于等于26。
第一行为前序遍历,第二行为中序遍历。
二叉树中的结点名称以大写字母表示:A,B,C....最多26个结点。

输出:

输入样例可能有多组,对于每组测试样例,
输出一行,为后序遍历的字符串。

样例输入:
ABC
BAC
FDXEAG
XDEFAG
样例输出:
BCA
XEDGAF

这道题也费了我一番功夫,主要用递归来解题时要考虑到左子树或右子树不存在的情况
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <string>
 5  
 6 #define MAX 30
 7  
 8 char front[MAX];
 9 char middle[MAX];
10  
11 void backOut(int start, int end, int fb) {
12     if(start == end) {
13         printf("%c",front[fb]);
14         return;
15     }
16     int wei;
17     for(int i = start; i <= end; i++) {
18         if(middle[i] == front[fb]) {
19             wei = i;
20             break;
21         }
22     }
23     //only right
24     if(wei == start) {
25         backOut(wei+1,end, wei-start+fb+1);
26     }//only left
27     else if(wei == end) {
28         backOut(start, wei-1, fb+1);
29     }
30     else {
31         backOut(start, wei-1, fb+1);
32         backOut(wei+1,end, wei-start+fb+1);
33     }
34     printf("%c",front[fb]);
35 }
36  
37 int main(int argc, char const *argv[])
38  {
39  
40     while(scanf("%s %s",front,middle) != EOF) {
41         backOut(0, strlen(front)-1, 0);
42         printf("
");
43     }
44     return 0;
45  } 
原文地址:https://www.cnblogs.com/jasonJie/p/5725217.html