题目描述
输入两个整数 a, b,输出它们的和(∣a∣,∣b∣≤109)。
注意
- Pascal 使用 integer 会爆掉哦!
- 有负数哦!
- C/C++ 的 main 函数必须是 int 类型,而且 C 最后要 return 0。这不仅对洛谷其他题目有效,而且也是 NOIP/CSP/NOI 比赛的要求!
好吧,同志们,我们就从这一题开始,向着大牛的路进发。
任何一个伟大的思想,都有一个微不足道的开始。
输入格式
两个以空格分开的整数。
输出格式
一个整数。
输入输出样例
输入 #1复制
20 30
输出 #1复制
50
大家入门时都应做过这样一道题吧。
但请注意:题目给的数据范围是小于10^9.
如是我们可以给出下面的代码:
#include <iostream>
#include <cstdio>
//万能头: #include<bits/stdc++.h>
using namespace std;
int main()
{
int a,b;
cin >> a >> b;
cout << a+b << endl;
return 0;
}
但如果是10^100呢?(不考虑int_128)
我们常用的int、long long甚至是unsigned long long都无法满足需求。这时候——
高精度闪亮登场!
那么:高精度到底有多“精”呢?
说实话,高精度没有上限!
洛谷 P1601 A+B Problem
题目描述
高精度加法,相当于a+b problem,不用考虑负数.
输入格式
分两行输入。a,b≤10^500
输出格式
输出只有一行,代表a+b的值
输入输出样例
输入 #1复制
1 1
输出 #1复制
2
输入 #2复制
1001 9099
输出 #2复制
10100
这里我们可以看到:数据范围是10^500!
那么怎么写呢?
我们可以用之前讲过的字符数组来解决问题。
char a[505], b[505];
那么为什么不能用普通数组呢?
普通数组需要以换行来结束输入。辣么长一个数,你全存在数组中的一个变量中——你要高精度干嘛?字符数组则是输入一个字符就结束输入……于是你就将辣么长一个数分别存在了许多变量中(只不过之后转整数有些麻烦)
#include <bits/stdc++.h>
using namespace std;
char a[505], b[505];
int main(){
scanf("%s", &a);
scanf("%s", &b);
小学加法怎么算?
列 竖 式 !
举例: 9 3 9
+ 6 4 8
———————1————— //进位
1 5 8 7
那么我们就可以按这样的思路一位一位地加……
但是计算机需要知道你的位数,不然一直加加加……000000……
怎么确定位数呢?
:strlen !!!
strlen所作的是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值(长度不包含'\0')。 ——百度百科
#include <bits/stdc++.h>
using namespace std;
int l1, l2;
char a[505], b[505];
int main(){
scanf("%s", &a);
scanf("%s", &b);
l1=strlen(a);
l2=strlen(b);
接下来就是将字符数组转换为整型数组的过程。(字符无法进行运算!)(注意倒序):
#include <bits/stdc++.h>
using namespace std;
int numa[505], numb[505] l1, l2, l, cnt2;
char a[505], b[505];
int main(){
scanf("%s", &a);
scanf("%s", &b);
l1=strlen(a);
l2=strlen(b);
for(int i=l1-1; i>=0; --i){
numa[l1-i-1]=a[i]-'0'; //第一种写法
}
for(int i=l2-1; i>=0; --i){
numb[cnt2]=b[i]-'0'; //第二种写法
cnt2++;
}
l=max(l1, l2); //计算最长位数
为什么要计算最长的位数?
不然就像505+1654,只考虑后三位,那前面的1怎么办?
细节:提前存储好l,不然会很费时间(max函数也费时间)。
接下来就到了列竖式的时间了:
#include <bits/stdc++.h>
using namespace std;
int numa[505], numb[505], ans[505], l1, l2, l, cnt2;
char a[505], b[505];
int main(){
scanf("%s", &a);
scanf("%s", &b);
l1=strlen(a);
l2=strlen(b);
for(int i=l1-1; i>=0; --i){
numa[l1-i-1]=a[i]-'0';
}
for(int i=l2-1; i>=0; --i){
numb[cnt2]=b[i]-'0';
cnt2++;
}
l=max(l1, l2);
for(int i=0; i<l; ++i){
ans[i]+=numa[i]+numb[i]; //相加
ans[i+1]=ans[i]/10; //进位处理
ans[i]%=10;
}
如果有进位怎么办?
505+666=1171
不处理的话,输出会变成:171!
然鹅加法只能进一位,所以只处理一次就够了:
#include <bits/stdc++.h>
using namespace std;
int numa[505], numb[505], ans[505], l1, l2, l, cnt2;
char a[505], b[505];
int main(){
scanf("%s", &a);
scanf("%s", &b);
l1=strlen(a);
l2=strlen(b);
for(int i=l1-1; i>=0; --i){
numa[l1-i-1]=a[i]-'0';
}
for(int i=l2-1; i>=0; --i){
numb[cnt2]=b[i]-'0';
cnt2++;
}
l=max(l1, l2);
for(int i=0; i<l; ++i){
ans[i]+=numa[i]+numb[i];
ans[i+1]=ans[i]/10;
ans[i]%=10;
}
if(ans[l]){ //如果前面有数,即不为0
l++; //位数加1
}
倒序输出:
#include <bits/stdc++.h>
using namespace std;
int numa[505], numb[505], ans[505], l1, l2, l, cnt2;
char a[505], b[505];
int main(){
scanf("%s", &a);
scanf("%s", &b);
l1=strlen(a);
l2=strlen(b);
for(int i=l1-1; i>=0; --i){
numa[l1-i-1]=a[i]-'0';
}
for(int i=l2-1; i>=0; --i){
numb[cnt2]=b[i]-'0';
cnt2++;
}
l=max(l1, l2);
for(int i=0; i<l; ++i){
ans[i]+=numa[i]+numb[i];
ans[i+1]=ans[i]/10;
ans[i]%=10;
}
if(ans[l]){ //如果前面有数,即不为0
l++; //位数加1
}
for(int i=l-1; i>=0; --i){
printf("%d", ans[i]);
}
return 0;
}
完整代码(注释版):
#include <bits/stdc++.h>
using namespace std;
int numa[505], numb[505] l1, l2, l, cnt2;
char a[505], b[505];
int main(){
scanf("%s", &a);
scanf("%s", &b);
l1=strlen(a);
l2=strlen(b);
for(int i=l1-1; i>=0; --i){
numa[l1-i-1]=a[i]-'0'; //第一种写法
}
for(int i=l2-1; i>=0; --i){
numb[cnt2]=b[i]-'0'; //第二种写法
cnt2++;
}
l=max(l1, l2); //计算最长位数
for(int i=0; i<l; ++i){
ans[i]+=numa[i]+numb[i]; //相加
ans[i+1]=ans[i]/10; //进位处理
ans[i]%=10;
}
if(ans[l]){ //如果前面有数,即不为0
l++; //位数加1
}
for(int i=l-1; i>=0; --i){ //倒序输出
printf("%d", ans[i]);
}
return 0;
}
附高精减及高精乘代码:
1.高精减:
#include<bits/stdc++.h> using namespace std; char a[20000],b[20000]; int c[20000],d[20000],e[20000]; int l1,l2,p; bool k=0,m=0; int main(){ cin>>a>>b; l1=strlen(a); l2=strlen(b); p=l2; for(int i=0;i<=l1;i++){ c[l1-i]=a[i]-'0'; } for(int i=0;i<=l2;i++){ d[l2-i]=b[i]-'0'; } if(l1>=l2){ p=l1; for(int i=1;i<=p;i++){ swap(c[i],d[i]); } } else{ m=1; } for(int i=1;i<=p;i++){ swap(c[i],d[i]); } for(int i=p;i>=0;i--){ if (c[i]>d[i]){ break; } if(c[i]<d[i]){ k=1; break; } } if(k){ m=1; for(int i=0;i<p;i++){ swap(c[i],d[i]); } } for(int i=0;i<=p;i++){ e[i]+=c[i]-d[i]; if(e[i]<0){ e[i]+=10; e[i+1]-=1; } } k=0; if(m){ cout<<"-"; } for(int i=0;i<p;i++){ if(e[p-i]!=0||i==p-1){ k=1; } if(k){ cout<<e[p-i]; } } return 0; }
2.高精乘:
#include <bits/stdc++.h> using namespace std; int numa[260], numb[260], ans[260], l1, l2, l, cnt2; char a[260], b[260]; int main(){ scanf("%s", &a); scanf("%s", &b); l1=strlen(a); l2=strlen(b); for(int i=l1-1; i>=0; --i){ numa[l1-i-1]=a[i]-'0'; } for(int i=l2-1; i>=0; --i){ numb[cnt2]=b[i]-'0'; cnt2++; } l=max(l1, l2); for(int i=0; i<l1; ++i){ for(int j=0;j<l2;j++){ ans[i]+=(numa[i]*numb[j])*pow(10,j); } ans[i+1]=ans[i]/10; ans[i]%=10; } if(ans[l]){ l++; } for(int i=l-1; i>=0; --i){ printf("%d", ans[i]); } return 0; }