携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情
AcWing 793. 高精度乘法
给定两个非负整数(不含前导 0) A 和 B,请你计算 A×B 的值。
输入格式
共两行,第一行包含整数 A,第二行包含整数 B。
输出格式
共一行,包含 A × B 的值。
数据范围
1 ≤ A的长度 ≤ 100000,
0 ≤ B ≤ 10000
输入样例:
2
3
输出样例:
6
思路
高精度乘法
数字逆序存储,数组从第一个位置开始循环计算,即为数字的个位开始计算,每次乘完 都要加上进位,每次计算后 %10,即为当前位置的数字, /10 代表给下一位置的进位 ,逆序输出
高精度乘法 A * b (len(A) 几千位,b <= 9位数) 从低位到高位计算 c[i] = (A[i] * b) % 10, 进位 t = (A[i] * b) / 10; 计算完之后如果 t大于0,记得把 t的每一位加到 c数组最后
高精度乘低精度模板
// C = A * b, A >= 0, b >= 0
vector<int> mul(vector<int> &A, int b){
vector<int> C;
int t = 0;
for (int i = 0; i < A.size() || t; i ++ ){
if (i < A.size()) t += A[i] * b;
C.push_back(t % 10);
t /= 10;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
高精度 x 高精度
vector<int> mul(vector<int> &A, vector<int> &B) {
vector<int> C(A.size() + B.size() + 7, 0); // 初始化为 0,C的size可以大一点
for (int i = 0; i < A.size(); i++)
for (int j = 0; j < B.size(); j++)
C[i + j] += A[i] * B[j];
int t = 0;
for (int i = 0; i < C.size(); i++) { // i = C.size() - 1时 t 一定小于 10
t += C[i];
C[i] = t % 10;
t /= 10;
}
while (C.size() > 1 && C.back() == 0) C.pop_back(); // 必须要去前导 0,因为最高位很可能是 0
return C;
}
ac代码
#include<iostream>
#include<vector>
using namespace std;
vector <int> mul(vector<int> &A,int b){
vector<int> C;
int t =0;
for(int i=0;i<A.size()||t;i++){
if(i<A.size()) t+=A[i]*b;
C.push_back(t%10);
t/=10;
}
while(C.size()>1&&C.back() == 0) C.pop_back();
return C;
}
int main(){
string a;
int b;
cin>>a>>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--) printf("%d", C[i]);
return 0;
}
AcWing 794. 高精度除法
给定两个非负整数(不含前导 0) A,B,请你计算 A/B 的商和余数。
输入格式
共两行,第一行包含整数 A,第二行包含整数 B。
输出格式
共两行,第一行输出所求的商,第二行输出所求余数。
数据范围
1 ≤ A的长度 ≤ 100000,
1 ≤ B ≤ 10000,
B 一定不为 00
输入样例:
7
2
输出样例:
3
1
思路
高精度除法
逆序存储数字
从数组的最后一位开始循环计算,即为数字的最高位开始计算;使用 r 代表当前计算的差,
r * 10 + a[i] 表示当前计算的被减数,r / b表示当前数位的结果,r % b表示当前计算的差值;
计算到最后 r 就是余数,去除前导数0后,逆序输出
(高精度) O(n^2) 高精度除法要求求出商和余数,那我们的思路就是:把上一次的余数乘10,再加上当前位上的数,就是被除数,后面往C(答案)里压入这个数字除以b,就可以得到商在这个位置上的数字。
高精度除法 A / b (len(A) 几千位,b <= 9位数, 注意有商c和余数r) (注意点高位到低位计算,计算完记得反转商) 从高位到低位计算, r = r * 10 + A[i], c[i] = r / b, r = r % b
高精度除以低精度模板
// A / b = C ... r, A >= 0, b > 0
vector<int> div(vector<int> &A, int b, int &r){
vector<int> C;
r = 0;
for (int i = A.size() - 1; i >= 0; i -- ){
r = r * 10 + A[i];
C.push_back(r / b);
r %= b;
}
reverse(C.begin(), C.end());
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
ac代码
#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;
}