zoukankan      html  css  js  c++  java
  • 清华大学 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  } 
  • 相关阅读:
    springboot运行时该注意的地方
    建立第一个SpringBoot小列子(碰到的错误)
    mysql建表基本语法
    两层c:forEach循环嵌套
    git-------基础知识(本地推送项目版本---github上)
    《生活的邀请函》___ 奥雷阿
    输入路径(包括盘符),打印层级目录(隐藏文件也会打印出来)
    输入两个文件夹路径,把其中一个文件夹中(包含内容)拷贝到另一个文件夹中
    用java实现歌曲串烧高速版(SequenceInputStream的使用)
    Java中InputStream装饰器模式的大家族
  • 原文地址:https://www.cnblogs.com/jasonJie/p/5725217.html
Copyright © 2011-2022 走看看