问题引入
输入两个数a,b,输出a+b
其中
1
≤
a
,
b
≤
1
0
1000
1\le a,b \le 10^{1000}
1≤a,b≤101000
此时,正常的输入已近炸了,所以对于蒟蒻来说要使用高精度。
介绍
高精度算法(High Accuracy Algorithm)是处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储,于是,将这个数字拆开,拆成一位一位的,或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。高精度算法就是能处理高精度数各种运算的算法,但又因其特殊性,故从普通数的算法中分离,自成一家。
原理
想一想,你是如何做加法的,如果让你做114514+1919810你是不是如下图做的:
我们从末位开始,每次相加,满十进一。
所以我们可以用数组来模拟这一个过程。
代码实现
转字符
由于输入的数太大了,我们用字符串输入,再把它转成数字存在数组中。
string s,a,b;
cin>>a>>b;
const int N=1001;
int na[N],nb[N],nc[N],lena=a.size(),lenb=b.size();
fill(na,na+N,0);
fill(nb,nb+N,0);
fill(nc,nc+N,0);
for(int i=lena-1;i>=0;i--)
na[lena-i]=a[i]-'0';
for(int i=lenb-1;i>=0;i--)
nb[lenb-i]=b[i]-'0';
开始
由于我们是倒着存字符串的,所以我们现在可以直接从1开始相加,模拟原来的从末位开始相加。
e.g.
for(int i=1;i<=lenc;i++)
nc[i]+=na[i]+nb[i],nc[i+1]+=nc[i]/10,nc[i]%=10;
解释:
na,nb为输入的字符串转成的数字,nc为答案数组。
同时,我们还要模拟进位,及:
n
c
[
i
+
1
]
+
=
n
c
[
i
]
/
10
,
n
c
[
i
]
−
=
10
nc[i+1]+=nc[i]/10,nc[i]-=10
nc[i+1]+=nc[i]/10,nc[i]−=10
注意,前提是
n
c
[
i
]
≥
10
nc[i]\geq10
nc[i]≥10,所以这里推荐像上面那样打。
去前导0
单单运算完上面两步还是不够的,我们还要去前导0。
不去有惊喜
方法也很简单,碰到第一个非0数字就break。
同时,要判断答案为0的存在。
while(nc[lenc]==0&&lenc>1)
lenc--;
例题
题目
输入两个数
a
,
b
a,b
a,b,输出
a
+
b
a+b
a+b
其中
1
≤
a
,
b
≤
1
0
1000
1\le a,b \le 10^{1000}
1≤a,b≤101000
输入格式
- 第一行两个整数a和b
输出格式
- 共一行,输出a+b
输入/输出例子
样例解释
无
Code
#include<bits/stdc++.h>
using namespace std;
string a,b;
string add(string a,string b)
{
string s;
cin>>a>>b;
const int N=1001;
int na[N],nb[N],nc[N],lena=a.size(),lenb=b.size();
fill(na,na+N,0);
fill(nb,nb+N,0);
fill(nc,nc+N,0);
for(int i=lena-1;i>=0;i--)
na[lena-i]=a[i]-'0';
for(int i=lenb-1;i>=0;i--)
nb[lenb-i]=b[i]-'0';
int lenc=max(lena,lenb)+10;
for(int i=1;i<=lenc;i++)
nc[i]+=na[i]+nb[i],nc[i+1]+=nc[i]/10,nc[i]%=10;
while(nc[lenc]==0&&lenc>1)
lenc--;
for(int i=lenc;i>=1;i--)
s+=nc[i]+'0';
return s;
}
signed main()
{
cin>>a>>b;
cout<<add(a,b);
}