洛谷 P1009 阶乘之和 (高精度算法)

无论是 int  还是 long long  还是 unsigned long long 型都无法计算到50的阶乘

int  四个字节    32位      范围:-2^31——2^31 -1      10^9次方数量级

unsigned long long  8个字节  64位    范围0——2^64 -1     10^19次方数量级 

显然 50的阶乘  远超 上述数量级

所以这里常规方法 不在适用     引入 高精度算法   概念   适用 +-*/

 

其基本方法就是就是引入数组

比如上述50的阶乘 常规方法没法存下它   但是 int arr[1000]  这个数字肯定可以存下它  50!的每一位存在一个数组元素里面 这样就解决了 大数的乘法 

但是值得注意的是 对于50!(30414093201713378043612608166064768844377641568960512000000000000)这个数的话我们往 整型数组 里面放  比较繁琐 需要一个一个的放。

这里引入如下代码:

char arr1[1000]="304140932017133780436126081660647688440512000000000000";

int arr2[1000]={0};

int sz=strlen(arr1);   //求字符串长度

for(int i=0;i<sz;++i)

{

arr2[i]=arr1[sz-1-i]-'0';      //字符串在内存中存的是 ASC|| 码  这里减‘0’; 就把它还原成本来的数字

}

由上述代码  即可实现大数的写入   

 这里解释为什么逆序给他存入arr2的   因为我们做算数都是从各位开始的 ,所以逆序存入,方便向高进位!!!

对于本题 用不到上述方法   因为这里是从 1往上乘的   不用存入大数

代码如下:


//最终优化版本
#include<stdio.h>
#include<string.h>
//高精度算法
int arr2[100] = { 0 };
int main()
{

	int n = 0;
	int a = 0;
	scanf("%d", &n);
	int i = 1;
	int arr2[1000] = {1};//存放阶乘 
	int arr4[1000] = { 0 };
	for (i = 1; i <= n; ++i)

	{

		阶乘
		
		int flag = 0; //进位标志

		int j = 1;
		for(j=0;j<1000;++j)
		{
			arr2[j] = (arr2[j] * i) + flag;
			flag = arr2[j] / 10;
			arr2[j] = arr2[j] % 10;
		}
		求和  
	
		flag = 0; //进位标志
		j = 1;
		for(j=0;j<1000;++j)
		{
			arr4[j] = arr4[j] + arr2[j] + flag;
			flag = arr4[j] / 10;
			arr4[j] = arr4[j] % 10;
		}

		
		

	}


	for (int j = 999; j >= 0; --j)
	{
		if (arr4[j] != 0)
		{
			a = j;
			break;
		}
	}
	
	for(i=a;i>=0;--i)
	printf("%d", arr4[i]);


	return 0;
}

对于阶乘部分解释:数字的低位在低地址  高位在高地址 

代码比较好理解 不多坠入   

+ - / 同理

记住高精度的算法的精髓 :利用数组 来存放结果!!!!

                             数字的低位在低地址  高位在高地址

一方面:方便向高位进位  

另一方面就是:做加减法  位权相同的要对齐   都从数组arr[0]开始 自然就对齐了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值