一张美图,平复一下心情…
好的正文开始咯:
首先,对于高精度做一下基本解释,当longlong对100!无能为力时,我们企图找到另一种方法来解决问题,没错就是***数组***了,当然你可能看到有的人说用***字符串***数组,有的人说用***int数组,其实都是根据问题来选择的。
使用起来也都一样,无非是前者需要减去‘0’或者48,(ascll码),最重要的还是 思想;来分析一下:
第一点
100100=10,000 5位;
999999=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;
}