提供50的阶乘30414093201713378043612608166064768844377641568960512000000000000;
显然要做这题,int 或者 long long 类型的整型放不下这么长的数据所以我们要使用数组用高精度实现;
然后容易想到这题 肯定要用到高精度乘法和高精度加法;
进一步思考,如
算一个数的阶乘,比方说我们算 5 的阶乘难道要分别算完五个数的阶乘再相加吗,显然时间复杂度是很高的,
所以我们可以考虑设计一个比方说算到5的阶乘就可以把1 2 3 4 的阶乘都给存起来,然后根据一定的特性把这些数全加起来;
long long a[51][200] = {0};//存初始数
long long b[51][200] = {0};//存放阶乘
long long c[51][200] = {0};//存放阶乘和
这么构思的思考是:既能根据单调特性方便写循环,又能直线的得出答案降低时间复杂度;
#include<stdio.h>
void f1(long long a[51][200],long long b[51][200],int i){
int p1,p2,m1,m2,m3;
for(p1=0;p1<=1;p1++){
for(p2=0;p2<=99;p2++){
b[i][p1+p2]=b[i-1][p2]*a[i][p1]+b[i][p2+p1];
}}
for(m1=0;m1<=99;m1++){
if(b[i][m1]>=10) {
m2 = b[i][m1]%10;
m3 = b[i][m1]/10;
b[i][m1] = m2;
b[i][m1+1] = m3 + b[i][m1+1];
}
}
}
void f2(long long b[51][200],long long c[51][200],int j){
int x1,x2;
for(x1=0;x1<=99;x1++){
c[j][x1]=b[j][x1]+c[j-1][x1];
}
for(x2=0;x2<=99;x2++){
if(c[j][x2]>=10){
c[j][x2+1]=1+c[j][x2+1];
c[j][x2]=c[j][x2]%10;
}
}
}
int main(){
long long a[51][200] = {0};//存初始数
long long b[51][200] = {0};//存放阶乘
long long c[51][200] = {0};//存放阶乘和
int i,j,n,k1,k2,z,v;
scanf("%d",&n);
for(i=1;i<=n;i++){
if(i>=10){
k1 = i%10;
k2 = i/10;
a[i][0] = k1;
a[i][1] = k2;
}
else a[i][0] = i;
}//将位数上的数字按照从小到大排列
b[0][0] = 1;
for(i=1;i<=n;i++){
f1(a,b,i);//实现乘法
}
for(j=1;j<=n;j++){
f2(b,c,j);//实现加法
}
for(z=199;z>=0;z--){
if(c[n][z]!=0)break;//输入后往前输入,只要不等于0说明这个数字已经开始
}
for(v=z;v>=0;v--){
printf("%lld",c[n][v]);//输出
}
}
这里说明乘法,后一位遍乘数组的比前一位遍乘数组的,整体放的数组位要向后挪一位;
这里有一个小trick: b[0][0]赋值为1是方便启动乘法