题目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("\n"); 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("\n"); 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("\n"); 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\n", 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("\n"); 43 } 44 return 0; 45 }
时间: 2024-10-09 13:47:05