PTA 阶乘计算升级版 C语言 双向链表

目录

函数接口定义

裁判测试程序样例

输入样例

输出样例

算法思想

代码

提交结果


实现一个打印非负整数阶乘的函数。

函数接口定义

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 的阶乘运算。


提交结果

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值