高精度加法
思路:将数反过来存储,从个位加起,用t来表示是否进位
模板:
#include<iostream>
#include<vector>
using namespace std;
int i;
vector<int> add(vector<int> &A,vector<int> &B)
{
if(A.size()<B.size()) return add(B,A);//大的数字在前面,小的在后面
int t=0;
vector<int> c;
for(int i=0;i<A.size()||i<B.size();i++)
{
if(i<A.size())
t+=A[i];//进位加第一位数字的一位数
if(i<B.size())
t+=b[i];//加第二位数字的一位数
c.push_back(t%10);
t/=10;//求进位
}
if(t) c.push_back(t);//最后一位进位如果是1则直接在最前面写1,如果是0,则忽略不写
return c;
}
int main()
{
string a,b;
vector<int> A,B;
cin>>a>>b;
for(int i=a.size-1;i>=0;i--) A.push_back(a[i]-'0');//将a的数字顺序倒过来
for(int i=b.size-1;i>=0;i--) B.push_back(b[i]-'0');//将b的数字顺序倒过来
auto c=add(A,B);//auto表示自动识别c的类型
for(int i=c.size-1;i>=0;i++) printf("%d ",c[i]);//将c的数字顺序倒过来,输出正确的结果c
return 0;
}
例题791
题目:
给定两个正整数,计算它们的和。
输入格式
共两行,每行包含一个整数。
输出格式
共一行,包含所求的和。
答案
#include <iostream>
using namespace std;
const int N = 100010;
int A[N], B[N], C[N];
int Add(int a[], int b[], int c[], int cnt) {
int t = 0;//t表示进位
for (int i=1; i<=cnt; i++) {
t += a[i] + b[i]; //进位加上a和b第i位上的数
c[i] = t % 10; //c的值就是进位的个位数
t /= 10; //把t的个位数去掉只剩下十位数,即只剩下这个位置的进位
}
if (t) c[++cnt] = 1; //如果t==1,表示还有一个进位,要补上
return cnt;
}
int main() {
string a, b;
cin >> a >> b; //A和B倒着放进int数组,因为有进位,倒着放容易处理
int cnt1 = 0;
for (int i=a.size()-1; i>=0; i--)
A[++cnt1] = a[i] - '0';
int cnt2 = 0;
for (int i=b.size()-1; i>=0; i--)
B[++cnt2] = b[i] - '0';
int tot = Add(A, B, C, max(cnt1, cnt2)); //因为A和B是倒着放的,所以C也要倒着输出
for (int i=tot; i>=1; i--)
cout << C[i];
}
例题792
题目
对两个大精度正整数做差,这里注意前后的数据处理0;
样例
输入
002
10
输出
-8
答案
#include <iostream>
#include <vector>
using namespace std;
const int N = 1000010;
bool cmp(vector<int> &A, vector<int> &B)
{
if (A.size() != B.size()) return A.size() >= B.size();
for (int i = A.size() - 1; i >= 0; i--)
if (A[i] != B[i])
return A[i] > B[i];
return true;
}
void trimZero(vector<int> &A)
{
while (A.back() == 0 && A.size() > 1) A.pop_back();
}
vector<int> sub(vector<int> &A, vector<int> &B)
{
vector<int> C;
int t = 0;
for (int i = 0; i < A.size(); i++)
{
t = A[i] - t;
if (i < B.size()) t -= B[i];
C.push_back((t + 10) % 10);
if (t < 0) t = 1;
else t = 0;
}
trimZero(C);
return C;
}
int main()
{
string a, b;
cin >> a >> b;
vector<int> A, B, C;
for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
for (int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');
trimZero(A), trimZero(B);
if (cmp(A, B)) C = sub(A, B);
else {
C = sub(B, A);
printf("-");
}
for (int i = C.size() - 1; i >= 0; i--) cout << C[i];
return 0;
}
作者:goontry
链接:https://www.acwing.com/solution/content/2082/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
例题793
题目
给定两个正整数A和B,请你计算A * B的值。
输入格式
共两行,第一行包含整数A,第二行包含整数B。
输出格式
共一行,包含A * B的值。
数据范围
1≤A的长度≤100000,
1≤B≤10000
答案
#include <bits/stdc++.h>
#include <iostream>
#include <string.h>
using namespace std;
const int N = 100010;
int main()
{
long long b,la,i,t=0;
char sa[N];
scanf("%s",&sa);
scanf("%ld",&b);
int a[N],c[N];
la=strlen(sa);
//字符转数字,并倒叙存入 方便运算
for(i = la-1; i >= 0; i--)
a[la-i-1]=sa[i]-'0';
//如果乘的a数组结束或 或者暂存值的t结束了退出
for(i=0;i<la||t;i++){
//乘法是否结束
if(i<la) t+=a[i]*b;
//转存值
c[i]=t%10;
t/=10;
}
//去除前缀零 0023*0=0
while(c[i-1]==0&&i>1)i--;
//输出结果
for(int j=i-1;j>=0;j--)
printf("%d",c[j]);
return 0;
}
例题794
题目
给定两个正整数A,B,请你计算 A / B的商和余数。
输入格式
共两行,第一行包含整数A,第二行包含整数B。
输出格式
共两行,第一行输出所求的商,第二行输出所求余数。
数据范围
1≤A的长度≤100000,
1≤B≤10000
答案
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//int r=0;
vector<int> div(vector<int> &A,int B,int &r){//r传入r的地址,便于直接对余数r进行修改
vector<int> C;
for(int i=0;i<A.size();i++){//对A从最高位开始处理
r=r*10+A[i];//将上次的余数*10在加上当前位的数字,便是该位需要除的被除数
C.push_back(r/B);//所得即为商在这一位的数字
r=r%B;
}
//由于在除法运算中,高位到低位运算,因此C的前导零都在vector的前面而不是尾部,vector只有删除最后一个数字pop_back是常数复杂度,而对于删除第一位没有相应的库函数可以使用,而且删除第一位,其余位也要前移,
//因此我们将C翻转,这样0就位于数组尾部,可以使用pop函数删除前导0
reverse(C.begin(),C.end());
while(C.size()>1&&C.back()==0) C.pop_back();
return C;
}
int main(){
string a;
int B,r=0; //代表余数
cin>>a>>B;
vector<int> A;
for(int i=0;i<a.size();i++) A.push_back(a[i]-'0');//注意这次的A是由高为传输至低位,由于在除法的手算过程中,发现从高位进行处理
//for(int i=0;i<A.size();i++) cout<<A[i];
//cout<<B;
auto C = div(A,B,r);
for(int i=C.size()-1;i>=0;i--) cout<<C[i];//将C从最高位传给最低位
cout<<endl<<r;//输出余数
cout<<endl;
return 0;
}
作者:过眼云烟1
链接:https://www.acwing.com/solution/content/2108/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。