目录
实现一个打印非负整数阶乘的函数。
函数接口定义
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
算法思想
由于整形变量最多表示 10 位十进制数(以下位数均表示十进制),因此,简单的循环累乘不足以满足超过 12 的阶乘计算。我们可以构建双向链表,在每个结点存放 6 位数,进行累乘进位运算。
每一轮运算从低位到高位依次计算,计算结果保留低 6 位并保存进位数 x ,进位数 x 参与下一个 6 位数字的计算,x 初始为0。
如果一轮运算结束后 x 大于0,则新建一个结点,用于存放进位 x 并链接在表尾,然后进行下一轮运算。总共进行 N - 1 轮运算。
最后,从高到低依次输出,除最高位的数以外,输出保留前面的 0。
以 N = 8,保留 2 位为例:
链表初始为:1(左:高位 表尾;右:低位 表头)
第一轮运算:1 * 8 = 8 进位x = 0;运算结束链表为:8
第二轮运算:8 * 7 = 56 进位x = 0;运算结束链表为:56
第三轮运算:56 * 6 = 336 保留 36,进位 x = 3;新建结点存放 3;运算结束链表为:3<-->36
第四轮运算:36 * 5 = 180 保留 80,x = 1;3 * 5 + 1 = 16 保留 16,x = 0;链表为:16<-->80
第五轮运算:80 * 4 = 320 保留 20,x = 3;16 * 4 + 3 = 67 保留 67,x = 0;链表:67<-->20
第六轮运算:20 * 3 = 60 保留 60,x = 0;67 * 3 + 0 = 201 保留 1,x = 2;新建结点存 2;链表:2<-->1<-->60(此时为 20160)
第七轮运算:60 * 2 = 120 保留 20,x = 1;1 * 2 + 1 = 3 保留 3,x = 0;2 * 2 + 0 = 4 保留 4,x = 0;链表:4<-->3<-->20。(结果为 40320,即 8!)
最后,从表尾到表头依次输出,除表尾外的数字输出保留前面的 0。
代码
#include <stdlib.h>
#include <math.h>
void Print_Factorial( const int N ){
int n=N, x,y;
typedef struct _node{
int data;
struct _node *next,*back;
}Node;
Node *head=(Node*)malloc(sizeof(Node)),*tail=head, *p;
head->data = 1;
head->next = head->back = NULL;
while (n> 1 ){
for ( p=head,x=0; p; p=p->next ){ //从低位开始,x存放进位数,初始为0
y = p->data*n + x;
p->data = y % (int)pow(10,6); //保留低6位
x = y / pow(10,6); //保存进位数x
}
if (x> 0 ){ //如果一轮运算结束后x大于0,新建结点,保存数据,链接
Node *np=(Node*)malloc(sizeof(Node));
np->data = x;
np->next = NULL;
tail->next = np;
np->back = tail;
tail = np;
}
n--;
}
if (N> 0 ){
for ( p=tail; p; p=p->back ){ //从高位到低位输出
if (p!= tail ) printf("%06d",p->data); //最高位以外保留前面的0
else printf("%d",p->data);
}
}else if (N== 0 ) printf("1"); //0!=1
else printf("Invalid input");//N小于0打印“Invalid input"
}
注意:若保留 7 位,则发生溢出。
上述算法可以满足一定范围内超过 1000 的阶乘运算。
提交结果