1.分类情况
A+B、A-B、A*a、A/b
A和B指的是超大超长整数,长度<=1e6;
a的值<=10000;
2.大整数的存储
int 变量肯定是存不了这么大的数的,做法是将大整数先存到string字符串,再使用字符串的访问方式,将每一位数存到数组中。
- 因为加减涉及到数字的进位问题,要在数组最后加一个数是简单的,但是要算在数组第一个下标处进一位是麻烦的
3.运算
模拟人工加法的过程,每次计算Ai+Bi+t
(t是上一次的进位,0或1)
高精度加法
- 模板:
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 /= 10;
}
if(t) C.push_back(1);
return C;
}
add(A,B);
注意在调用的时候和定义函数不同,直接传入就行,不用取址符号——引用
- main函数中将字符串转化为数字
string a;//"12345"
cin >> a;
for(int i = a.size()-1; i >= 0; i --)
A.push_back(a[i] - '0');//{5,4,3,2,1}
运算时还是根据ASCII表的数值,可以看到数组的字符形式的十进制和整形数字相差了一个字符 '0'
.
高精度减法
bool cmp(vector<int> &A, vector<int> &B)//判断是否有A>=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;
}
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];
if(t >= 0)
{
C.push_back(t);
t = 0;
}
else
{
C.push_back((t + 10) % 10);
t = 1;
}
}
//除去前导0
while(C.size() > 1 && C.back() == 0)
C.pop_back();
return C;
}
高精度x低精度
高精度乘法的算法和人计算乘法时的过程稍有不同。Axb
,A很长,使用string来储存,b很短,使用int即可。
将b看成一个整体去乘,而不是一位一位去乘。
vector<int> mul(vector<int> &A, int b)
{
vector<int> C;
int t = 0;
for(int i = 0; i < A.size(); i ++)
{
t = t + A[i] * b;
C.push_back(t % 10);
t = t / 10;
}
//处理最后的进位
while(t)
{
C.push_back(t % 10);
t = t / 10;
}
return C;
}
//注意在main函数中考虑b=0的情况,否则输出0000而不是0
if(b)
C = mul(A,b);
else
C.push_back(0);
高精度 / 低精度
模板:
vector<int> div(vector<int> &A, int b, int &x)
{
vector<int> C;
int r = 0;
for(int i = A.size() - 1; i >= 0; i --)
{
r = r * 10 + A[i];
C.push_back(r / b);
r = r % b;
}
x = r;
reverse(C.begin(),C.end());
while(C.size() > 1 && C.back() == 0)
C.pop_back();
return C;
}
注意除法是从A[]的高位开始除起,答案也是从高位开始存到C[]中。为了保证加减乘除格式的统一性,所以要在完成之后reverse(C.begin(),C.end());
反转一下保证储存顺序,当然在输出的时候也是反着输出,注意会出现前导0的情况出现。
在加减乘除算法中,减法和除法会出现前导零的情况;乘法会有特殊b = 0的存在.
4.刷题
对于未知的多组数据使用while(cin >> a >> b)
每次循环的时候要清空vector数组!
对于已知的多组数据使用cin >> n;while(n --)
,同样在必要时每次循环清空数组,重新输入!
题外
-
表示2的i次方:
1 << i 或者 #include<cmath> pow(2,i)
而不是2 ^ i
.在 C++ 中,^ 是按位异或运算符.
-
注意字符串使用双引号
" "
,char类型使用单引号' '
。 -
为了避免爆掉,有两种变量可以储存整数。
int
最多9位数;long long
最多18位数。 -
专门用于输出字符串的函数
puts(“No!”);
,并且它会自动在字符串末尾添加换行符。 -
==
运算符可以比较两个vector是否相等。
vector<int> A,C = ...
if (C == A) puts("Yes");
else puts("No");
如果两个vector的大小相等,并且所有对应位置的元素都相等,那么这两个vector相等。