基本思想——小学的竖式运算
决定了加,减,乘从低位运算到高位
除从高位到低位
一,高精度加法
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 100;
vector<int> addi(vector<int>&A, vector<int>&B)//使用&,可以直接引用,不然需要先复制才能用,如果这个容器太大,使用该函数次数过多,会被TLE,另一个意思,引用会修改原来的,没引用只是对形参操作
{
vector<int>C;
int t = 0;//用于进位
for (int i = 0; i < (int)A.size() || i < (int)B.size(); ++i)//i < (int)A.size() || i < (int)B.size()只要还有一个数的位还有,就进入
{
if (i < (int)A.size())t += A[i];//你有数,我就加
if (i < (int)B.size())t += B[i];
C.push_back(t % 10);
t /= 10;
}
if (t)C.push_back(t);//这里标志是否进位,有则存入
return C;
}
int main()
{
string a, b;
cin >> a >> b;
vector<int>A, B;
for (int i = (int)a.size() - 1; i >= 0; --i)A.push_back(a[i] - '0');//倒位存储
for (int i = (int)b.size() - 1; i >= 0; --i)B.push_back(b[i] - '0');
auto C = addi(A, B);//auto自动识别类型,避免写麻烦的容器类型
for (int i = (int)C.size() - 1; i >= 0; --i)cout << C[i];
return 0;
}
二,高精度减法
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 100;
bool cmp(vector<int>&A, vector<int>&B)//比较A,B大小
{
if ((int)A.size() != (int)B.size())return (int)A.size() > (int)B.size();
else
{
for (int i = (int)A.size() - 1; i >= 0; --i)
{
if (A[i] != B[i])return A[i] > B[i];//比较这一位的a,b
}
return 1;//注意,可能A,B相等,所以出来还要补这个
}
}
vector<int> sub(vector<int>&A, vector<int>&B)
{
vector<int>C;
int t = 0;//用于借位
for (int i = 0; i < (int)A.size(); ++i)
{
t = A[i] - t;//如果前面借位了,t是1,
if (i < (int)B.size())t -= B[i];//只要B还有位,减他
C.push_back((t + 10) % 10);//t+10是因为可能t不够减B[i],需要借位,给你个10保证
if (t < 0)t = 1;//t小于0,说明借位,赋值1,后面被减
else t = 0;
}
while ((int)C.size() > 1 && C.back() == 0)C.pop_back();//除去前导0
return C;
}
int main()
{
string a, b;
cin >> a >> b;
vector<int>A, B;
for (int i = (int)a.size() - 1; i >= 0; --i)A.push_back(a[i] - '0');
for (int i = (int)b.size() - 1; i >= 0; --i)B.push_back(b[i] - '0');
if (cmp(A, B))//我们保证一定是大的减去小的,返回真,那么A>=B
{
auto C = sub(A, B);
for (int i = (int)C.size() - 1; i >= 0; --i)cout << C[i];
}
else
{
auto C = sub(B, A);
cout << "-";//目标是A-B,但是为了方便,我们算法让他大数减小数,所以要补负号
for (int i = (int)C.size() - 1; i >= 0; --i)cout << C[i];
}
return 0;
}
三,高精度乘法(高精*低精)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 100;
vector<int> mul(vector<int>&A, ll b)
{
vector<int>C;
int t = 0;//每一位*b可能是好几位,所以t每次使用一位,/10,然后后面继续使用,也就是不能再以A的长度为结束为结束标志,只有同时t=0才可以结束
for (int i = 0; i < (int)A.size() || t; ++i)
{
if (i < (int)A.size()) t += A[i] * b;//所以这里t是+=,不再是= //+=A[i]*b,不要忘了*b
C.push_back(t % 10);//要加之前不忘这一句if (i < (int)A.size()),A没有是不能加的
t /= 10;
}
while (C.size() > 1 && !C.back())C.pop_back();//防止*0出现全0
return C;
}
int main()
{
string a;
ll b;
cin >> a >> b;
vector<int>A;
for (int i = (int)a.size() - 1; i >= 0; --i)A.push_back(a[i] - '0');
auto C = mul(A, b);
for (int i = (int)C.size() - 1; i >= 0; --i)cout << C[i];
return 0;
}
四,高精度除法
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 100;
vector<int> div(vector<int>&A, ll b, ll&r) //原函数r,函数&r,这是c++引用的一种,与指针很像
{
r = 0;
vector<int>C;
for (int i = (int)A.size() - 1; i >= 0; --i)
{
r = r * 10 + A[i];//r是余数,所以每次到下一位要先乘10再用
C.push_back(r / b);//竖式除
r %= b;//竖式取余
}
reverse(C.begin(), C.end());//因为我们是从高位正序存储到C中,所以用reverse全部逆序
while ((int)C.size() > 1 && !C.back())C.pop_back();//去前导0
return C;
}
int main()
{
string a;
ll b, r;
cin >> a >> b;
vector<int>A;
for (int i = (int)a.size() - 1; i >= 0; --i)A.push_back(a[i] - '0');
auto C = div(A, b, r); //r是余数,因为你可能最后除完还有剩
for (int i = (int)C.size() - 1; i >= 0; --i)cout << C[i];
cout << endl << r << endl;
return 0;
}
五,高精*高精
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int INF = 0x3f3f3f3f;
const int N = 2e5;
int C[N];//这里使用数组更容易操作
ll mul(vector<int>&A, vector<int>&B)
{
for (int i = 0; i < (int)A.size(); ++i)//遍历i,j
{
for (int j = 0; j < (int)B.size(); ++j)
{
C[i + j] += A[i] * B[j];//C是i+j位
}
}
for (int i = 0; i < (int)A.size() + (int)B.size(); ++i)
{
if (C[i] > 9)C[i + 1] += C[i] / 10;//累积后再单独对C操作
C[i] = C[i] % 10;
}
int len = (int)A.size() + (int)B.size();
while (!C[len - 1] && len > 1)len--;//除去前导0
return len;
}
int main()
{
string a, b;
vector<int>A, B;
cin >> a >> b;
for (int i = (int)a.size() - 1; i >= 0; --i)A.push_back(a[i] - '0');
for (int i = (int)b.size() - 1; i >= 0; --i)B.push_back(b[i] - '0');
ll len = mul(A, B);
for (ll i = len - 1; i >= 0; --i)cout << C[i];
return 0;
}