高精度题目类型
假定A和B为正数,大整数A、大整数B,A和B的位数大概是10^6。
- A-B
- A+B
- A*a(a为比较小的数)
- A/a
解题思路
1、大整数的存储
使用一个数组存储大整数,最低位下标为0
2、 模拟加法运算
每一位计算包含计算Ai+Bi+t(下一位的进位为0或者1),Ai或者Bi不存在就置0,最后如果有进位高位补1。
代码实现
1、大整数加法
#include<iostream>
#include<vector>//使用 vector表示大整数
using namespace std;
const int N = 1e6 +10;//1e6表示10^6,加10是为了防止边界问题
//加引用是为了提高效率,否则每执行一次函数数组都会被复制一遍
vector<int> add(vector<int> &A,vector<int> &B)
{
vector<int> C;
int t=0;//进位
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=t/10;
}
if(t) C.push_back(1);
return C;
}
或者
//加引用是为了提高效率,否则每执行一次函数数组都会被复制一遍
vector<int> add(vector<int> &A,vector<int> &B)
{
vector<int> C;
int t=0;//进位
if(A.size()<B.size()) return add(B,A);
for(int i=0;i<A.size();i++)
{
t+=A[i];
if(i<B.size())t+=B[i];//超出了长度就不对其进行加法运算
C.push_back(t%10);
t=t/10;
}
if(t) C.push_back(1);
return C;
}
int main()
{
string a,b;
vector<int>A,B;
cin>>a>>b;//a="123456"
//1、大整数使用数组存储
//逆序存放
for(int i=a.size()-1;i>=0;i--)A.push_back(a[i]-'0');//A=[6,5,4,3,2,1]
for(int i=b.size()-1;i>=0;i--)B.push_back(b[i]-'0');
//2、模拟加法
// auto让编译器自己推断变量是什么类型
auto C = add(A,B);
//倒序输出
for(int i=C.size()-1;i>=0;i--)
{
printf("%d",C[i]);
}
return 0;
}
2、大整数减法
#include<iostream>
#include<vector>//使用 vector表示大整数
using namespace std;
const int N = 1e6 +10;//1e6表示10^6,加10是为了防止边界问题
//判断A>=B?true:false
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;//A=B
}
//加引用是为了提高效率,否则每执行一次函数数组都会被复制一遍
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);//t>0进行加10模10运算还是本身;t<0就进行了借位操作
if(t<0) t=1;
else t=0;
}
//去掉前导0
// 如果C为0,必须要保留
//vector的back函数返回最末一个元素,pop_back移除vector中的最后一个元素
while(C.size()>1&&C.back()==0)
{
C.pop_back();
}
return C;
}
int main()
{
string a,b;
vector<int>A,B;
cin>>a>>b;//a="123456"
//1、大整数使用数组存储
//逆序存放
for(int i=a.size()-1;i>=0;i--)A.push_back(a[i]-'0');//A=[6,5,4,3,2,1]
for(int i=b.size()-1;i>=0;i--)B.push_back(b[i]-'0');
//2、模拟减法
if(cmp(A,B))//
{
auto C = sub(A,B);
//倒序输出
for(int i=C.size()-1;i>=0;i--)
{
printf("%d",C[i]);
}
}
else
{
auto C = sub(B,A);
printf("-");
//倒序输出
for(int i=C.size()-1;i>=0;i--)
{
printf("%d",C[i]);
}
}
return 0;
}
3、大整数乘法
#include<iostream>
using namespace std;
vector<int> mul(vector<int> &A,vector<int> B)
{
int t=0;
vector<int> C;
//||t是考虑到最后最高位仍有进位的情况
for(int i=0;i<A.size()||t;i++)
{
if(i<A.size())t+=A[i]*b;
C.push_back(t%10);
t/=10;
}
return C;
}
int main()
{
string a;
int b;//小整数
vector<int> A;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]='0');
auto C=mul(A,b);
for(int i=C.size()-1;i>=0;i--)prinf("%d",c[i]);
return 0;
}
4、高精度整数除以低精度整数
#include<iostream>
#include<algorithm>
using namespace std;
vector<int> div(vector<int> &A,int &b,int &r)
{
vector<int> C;
//从最高位开始算
for(int i=A.size()-1;i>=0;i--)
{
r=r*10+A[i];
C.push_back(r/b);
r=r%b;
}
reverse(C.begin(),C.end());
// C数组应该从低位开始存
//reverse在#include<algorithm>头文件
while(C.size()>1&&C.back()==0) C.pop_back();//去掉前导0
}
int main()
{
string a;
int b;//小整数
vector<int> A;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]='0');
int r;//余数
auto C=div(A,b,r);
for(int i=C.size()-1;i>=0;i--)prinf("%d",c[i]);
cout<<endl;
cout<<r<<endl;
return 0;
}