【题目描述】
求10000以内n的阶乘。
【输入】
只有一行输入,整数n(0<=n<=10000)。
【输出】
一行,即n!的值。
【输入样例】
4
【输出样例】
24
时间限制: 1000 ms 内存限制: 65536 KB
【代码】
先摆上正确的代码:
#include<bits/stdc++.h>
using namespace std;
int a[40000],h; //记录最高位,节省时间
void f(int n){ //函数递归
if(n==1){a[0]=1;return;}
f(n-1);
int x=0;
for(int i=0;i<=h+4;i++){ //利用x记录进位,一次循环搞定
a[i]*=n; //n小,直接乘
a[i]+=x;
x=a[i]/10;
a[i]%=10;
}
h+=4;
while(!a[h])h--;
}
int main(){
int n;
cin>>n;
f(n);
for(int i=h;i>=0;i--)cout<<a[i];
return 0;
}
或者直接用循环
#include<bits/stdc++.h>
using namespace std;
int a[36000],h;
int main(){
int n;
cin>>n;
a[0]=1;
for(int k=2;k<=n;k++){
int x=0;
for(int i=0;i<=h+4;i++){
a[i]*=k;
a[i]+=x;
x=a[i]/10;
a[i]%=10;
}
h+=4;
while(!a[h])h--;
}
for(int i=h;i>=0;i--)cout<<a[i];
return 0;
}
【做题过程】
这题难度很小,最基本的高精度计算。
关键是时间的问题,要注意,一不小心最后两个点就超时了。
下面是一步步改正的过程:
最开始的代码是这样的:
#include<bits/stdc++.h>
using namespace std;
int a[40000],c[40000];
void f(int n){
if(n==0){
a[0]=1;
return;
}
f(n-1);
int b[5];
for(int i=0;i<5;i++)b[i]=n%10,n/=10;
for(int i=0;i<40000;i++){
for(int j=0;j<5;j++){
c[i+j]+=a[i]*b[j];
}
}
for(int i=0;i<40000;i++){
if(c[i]>=10)c[i+1]+=c[i]/10,c[i]%=10;
a[i]=c[i];
c[i]=0;
}
return;
}
int main(){
int n;
cin>>n;
f(n);
int l=39999;
while(!a[l])l--;
for(;l>=0;l--)cout<<a[l];
return 0;
}
但最后两个点超时了。
然后想了一下,n其实很小,数组b没有存在的必要。
#include<bits/stdc++.h>
using namespace std;
int a[40000],c[40000];
void f(int n){
if(n==1){a[0]=1;return;}
f(n-1);
for(int i=0;i<40000;i++){
c[i]+=a[i]*n;
}
for(int i=0;i<40000;i++){
if(c[i]>=10)c[i+1]+=c[i]/10,c[i]%=10;
a[i]=c[i];
c[i]=0;
}
}
int main(){
int n;
cin>>n;
f(n);
int l=39999;
while(!a[l])l--;
for(;l>=0;l--)cout<<a[l];
return 0;
}
不过改了之后仍然没有过,后两个点依然超时了。
于是又想了一些办法改进:
记录位数,不仅可以大大减少函数f中的循环次数,主函数也中不用再循环一次去掉前导0;
删去c[40000],将函数f中的两次循环合并,此时需要用x记录进位。
这样就得到了最终的正确代码。
c++初学者,第一次写博客,请大家多多指教!