本题要求实现一个打印非负整数阶乘的函数。
函数接口定义
void Print_Factorial ( const int N );
其中N
是用户传入的参数,其值不超过1000。如果N
是非负整数,则该函数必须在一行中打印出N
!的值,否则打印“Invalid input”。
裁判测试程序样例:
#include <stdio.h>
void Print_Factorial ( const int N );
int main()
{
int N;
scanf("%d", &N);
Print_Factorial(N);
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例:
15
输出样例:
1307674368000
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
题解:
int型位数控制的实现
%05d
可以让输出控制为五位数,不足的高位用0补齐
1000的阶乘是2568位
写出来让人很有成就感的一题。首先尝试直接阶乘,但是即使使用longlong也会超出位数,于是想到手算乘法那样一位位的乘,但是那样好像过于复杂,假如阶乘得到的中间数有一位为9,此时乘以一个较大的数比如99时将得到一个三位数,甚至9*1000得到四位数,控制不确定位数的进位太过于复杂,于是想到以多位为一组,由于N<=1000,1000*99999<1010,只需要控制“一位”进位,因此选择以五位数为一组进行乘法运算。
void Print_Factorial ( const int N ){
if(N<0) printf("Invalid input");
else{
//printf("%010d",10);
int fac[600]={0};
fac[0]=1;
int x=N,k=0;
for(int i=2;i<=N;i++){
int temp=fac[0]*i;
if(k || temp/100000){//结果超过五位数
int flag=0,carry=0;//进位控制
for(int j=0;j<=k;j++){
temp=fac[j]*i;
fac[j]=temp%100000;
//if(i==14)printf("fac[%d]=%d temp=%d\n",j,fac[j],temp);
if(flag) {//加上上次的进位
int fleet=fac[j]+carry;
fac[j]=fleet%100000;
carry=0;//加完carry就马上将carry复位,以免影响下一次进位
//if(i==14)printf("carry%d+fac[%d]=%d ",carry,j,fac[j]);
carry+=(fleet/100000);//进位后再次产生进位的话
//if(i==14)printf("@%d\n",carry);
}
if(temp/100000){//如果进位,需要在下次循环加进去
flag=1;
carry+=(temp/100000);
if(j==k) k++;
//if(i==14)printf("here carry,carry=%d,k=%d\n",carry,k);
}
else {flag=0;carry=0;}//没有进位则需要还原flag和carry
}
}
else{//五位数内直接运算
fac[0]*=i;
}
}
for(int i=k;i>=0;i--){//分段输出结果
if(i==k) printf("%d",fac[i]);
else printf("%05d",fac[i]);
}
}
return ;
}
以为会有数学方法简化阶乘计算,结果看了很多答案都是这样的模拟竖式的方法,并且都是逐位相乘。