标签:
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1042
题意:
#include<iostream> #include<cstring> using namespace std; const int MAXN = 10000; int a[MAXN]; int main() { int N, k, temp; while(scanf("%d", &N)!=EOF) { memset(a, 0, sizeof(a)); a[0]=1; for(int i=1; i<=N; i++) { k=0; for(int j=0; j<MAXN; j++) { a[j]=a[j]*i+k; k=a[j]/10; a[j]%=10; } } int t; for(t=MAXN-1; t>=0; t--) if(a[t]) { //cout<<t<<endl; break; } for(int i=t; i>=0; i--) printf("%d", a[i]); printf("\n"); } return 0; }
上面的代码是不是和你的想法相同呢?, 很遗憾, 上述代码一定会超时! 那么 , 能不能把数组开小些呢? ----> 不能。 当N=10000时, 你会发现数组要开到9999。很明显, 这道题就是要卡你的时间, 就是要卡你的优化。 下面是两个优化思路:
1. 合并计算: 从而减少计算次数, 例如 你在每个a[i]中存10000数量级的数, 然后这个数组的长度就成2000啦! 但是这种算法在实现时要考虑很多情况, 比较繁琐!
2.过程优化: 由于结果值在计算时, 数位变化很大, 但是上述代码, 在计算时每次都按MAXN-1 位计算, 所以做了很多的无用功。如果每次计算时都顺带着算出位数, 这样就可以节省很多时间。代码只需稍加改动即可!
3.综合使用前两种方法!
由于第一和第三中方法较繁琐, 我不再理会!
#include<iostream> #include<cstdio> using namespace std; const int MAXN=100002; int a[MAXN]; int main() { int N; int k,count,temp; while(scanf("%d", &N)!=EOF) { a[0]=1; count=1; for(int i=1;i<=N;i++) { k=0; for(int j=0;j<count;j++) { temp=a[j]*i+k; a[j]=temp%10; k=temp/10; } while(k)//¼Ç¼½øλ { a[count++]=k%10; k/=10; } } for(int i=count-1;i>=0;i--) printf("%d", a[i]); printf("\n"); } return 0; }
耗时: 1045MS 时限是5s。
然而:
#include<iostream> #include<cstdio> using namespace std; const int MAXN = 100000; int main() { int n, a[MAXN]; int i, j, k, count, temp; while(cin>>n) { a[0]=1; count=1; for(i=1; i<=n; i++) { k=0; for(j=0; j<=count; j++) { temp=a[j]*i+k; a[j]=temp%10; k=temp/10; } while(k) { a[count++]=k%10; k/=10; } } for(j=MAXN-1; j>=0; j--) if(a[j]) break; for(i=count-1; i>=0; i--) cout<<a[i]; cout<<endl; } return 0; }
耗时: 811MS 很是令人费解! cin和cout不应该比scanf等慢吗? , 然而事实就是这样, 看来,书上说的也未必正确 。 虽然这个道理大家都懂, 但是不知不觉中还是迷信权威。 现实情况是千变万化的, 面对不同的情况会有意料之外的结果。 所以永远不要自以为是,永远不要把话说的太绝对, -------好像陷入悖论啦。 呵呵!
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
标签:
原文地址:http://www.cnblogs.com/acm1314/p/4619207.html