高精度 乘法和加法 求解阶乘之和 (附AC代码)

在这里插入图片描述一张美图,平复一下心情…
好的正文开始咯:
首先,对于高精度做一下基本解释,当longlong对100!无能为力时,我们企图找到另一种方法来解决问题,没错就是***数组***了,当然你可能看到有的人说用***字符串***数组,有的人说用***int数组,其实都是根据问题来选择的。
使用起来也都一样,无非是前者需要减去‘0’或者48,(ascll码),最重要的还是 思想;来分析一下:
第一点
100
100=10,000 5位;
999
999=998,001 6位;
这说明 一个 (长度为m的数)
(长度为n的数)的长度为m+n-1或者m+n,//是否最后一位进位,这句话现在看起来很懵懂,待会你就懂了;
第二点
我们小学就知道:竖式相乘
百位=个位*百位=十位十位;

在这里插入图片描述
我们之前做的话,是自右向左进位,这个想法是正常的,我之前也是这么想的,所以就绕进去了,为啥不好呢,因为每次找的话都要从尾部向前找到最低位,这样对于高精度乘法其实影响还不是那么大,但是对于高精度加法就很难受了,因为不好对齐,虽然有解决方法,我之前想到一种补前置“0”的对齐方法,仍旧很蛋疼,所以不如在这里就采用低位在左,自左向右进位的思想
在这里插入图片描述
声明一下,本题中所有数组都是从下表1开始,

在这里插入代码片void mul(int a[],int b[],int c[])
{
	int an,bn;
	for(an=200;an>=1;an--)//找出数组a的长度 
	{
		if(a[an]>0)
		break;
	} 
	for(bn=200;bn>0;bn--)//b的长度 
	{
		if(b[bn]>0)
		break;
	}
	for(int i=1;i<=bn;i++)//对位即可 
	{
		for(int j=1;j<=an;j++)
		{
			c[i+j-1]+=a[j]*b[i];//注意减一操作的好处哦
		}
	}
	for(int i=1;i<=an+bn-1;i++)
	{
		c[i+1]+=c[i]/10;//下一位=进位数+原来数 
		c[i]%=10;//本位 
	}
}

这里 数组a,b,c都是逆序的,有什么好处呢?c可以继续参与该精度乘法运算在这里插入图片描述
老婆大人让你好好学习,别走神…
剩下的就是一些接口问题了,至于加法,掌握了逆序,你老婆让你自己试一下。

在这里插入代码片void jiecheng(int d[],int k)
{
	int a[201],b[201],c[201];
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	memset(c,0,sizeof(c));
	a[1]=1;//给左乘数1个初值
	int t=1;//b的下标
	for(int i=1;i<=k;i++)
	{
		int i1=i;
		while(i1>0)//右乘数通过分解i得到,注意别用i,要不就是死循环了,别问我为啥知道的
		{
			b[t]=i1%10;
			i1=i1/10;
			t++;
		}
		mul(a,b,c);
		cover(a,c);//用c数组覆盖a数组
		/*for(int j=3;j>=1;j--)
		{
			cout<<a[j];
		}*/
	//	cout<<endl<<endl<<endl;
		memset(c,0,sizeof(c));//全部重置
		memset(b,0,sizeof(b));
		t=1;//b的下标
	}
	cover(d,a);//出口是d数组,仍旧是逆序的
}

加法主要是对齐位数就行,

在这里插入代码片void add(int a[],int b[],int c[])
{
	int an,bn;
	for(an=200;an>=1;an--)
	{
		if(a[an]>0)
		break;
	}
	for(bn=200;bn>=1;bn--)
	{
		if(b[bn]>0)
		break;
	}
	int n=max(an,bn);//找到最高位,因为是自左向右,位数短的那个数组的高位都是0,没影响;
	for(int i=1;i<=n;i++)
	{
		c[i]=a[i]+b[i];//同理先加完
	}
	for(int i=1;i<=n;i++)
	{
		c[i+1]+=c[i]/10;//再进位
		c[i]%=10;
	}
}
```![在这里插入图片描述](https://img-blog.csdnimg.cn/2020041017040470.png)
终于轮到我主代码了,虽然长了点,但是我感觉比较细致

```cpp
在这里插入代码片#include"iostream"
#include"string.h"
using namespace std;
void cover(int a[],int b[])
{	int i;
	for(i=200;i>=1;i--)
	{
		a[i]=0;
		if(b[i]>0)
		break;
	}
	for(int j=i;j>=1;j--)
	{
		a[j]=b[j];
	}
}
void mul(int a[],int b[],int c[])
{
	int an,bn;
	for(an=200;an>=1;an--)//找出数组a的长度 
	{
		if(a[an]>0)
		break;
	} 
	for(bn=200;bn>0;bn--)//b的长度 
	{
		if(b[bn]>0)
		break;
	}
	for(int i=1;i<=bn;i++)//对位即可 
	{
		for(int j=1;j<=an;j++)
		{
			c[i+j-1]+=a[j]*b[i];
		}
	}
	for(int i=1;i<=an+bn-1;i++)
	{
		c[i+1]+=c[i]/10;//下一位=进位数+原来数 
		c[i]%=10;//本位 
	}
}
void jiecheng(int d[],int k)
{
	int a[201],b[201],c[201];
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	memset(c,0,sizeof(c));
	a[1]=1;
	int t=1;
	for(int i=1;i<=k;i++)
	{
		int i1=i;
		while(i1>0)
		{
			b[t]=i1%10;
			i1=i1/10;
			t++;
		}
		mul(a,b,c);
		cover(a,c);
		/*for(int j=3;j>=1;j--)
		{
			cout<<a[j];
		}*/
	//	cout<<endl<<endl<<endl;
		memset(c,0,sizeof(c));
		memset(b,0,sizeof(b));
		t=1;
	}
	cover(d,a);
}
int max(int a,int b)
{
	return a>b?a:b;
}
void add(int a[],int b[],int c[])
{
	int an,bn;
	for(an=200;an>=1;an--)
	{
		if(a[an]>0)
		break;
	}
	for(bn=200;bn>=1;bn--)
	{
		if(b[bn]>0)
		break;
	}
	int n=max(an,bn);
	for(int i=1;i<=n;i++)
	{
		c[i]=a[i]+b[i];
	}
	for(int i=1;i<=n;i++)
	{
		c[i+1]+=c[i]/10;
		c[i]%=10;
	}
}
int main()
{
	int n;
	cin>>n;
	int sum[201],d[201],c[201]; 
	memset(sum,0,sizeof(sum));
	memset(d,0,sizeof(d));
	memset(c,0,sizeof(c));
	for(int i=1;i<=n;i++)
	{
		jiecheng(d,i);
		add(sum,d,c);
		cover(sum,c);
		memset(c,0,sizeof(c));
	}
	int i;
	for(i=200;i>=1;i--)
	{
		if(sum[i]>0)
		break;
	 } 
	 for(int j=i;j>=1;j--)
	 {
	 	cout<<sum[j];
	 }
	 return 0;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷鸟小fans

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值