以下纯属是自己学习csp过程中的一些记录,方便自己后续复盘,随心写,不必当真。
题目791:高精度加法
算法思想:
什么是高精度? A.length<<10e6 ,a<<10e9
然后在这个情况下进行加减乘除如 A+B、A-B、A*b、A/b等的组合就是高精度运算。
我们普通的加法手算如下:
例如计算:567 + 28
先个位相加: 7 + 8 = 15,所以结果的个位是5,向十位进 1
再十位相加: 6 + 2 + 1(进位)= 9, 所以十位是 9,向百位进 0
再百位相加: 5 + 0 = 5, 所以结果的百位是 5
综上,计算结果为 595
算法计算思路:
计算 567 + 28
用 a, b 两个字符串存储输入。a = 567, b = 28
为了方便计算,(因为加法要从各位开始,倒序存放符合计算规律)将两个数分别 倒序 存放在 A, B 两个整数数组中。 A = [7, 6, 5], B = [8, 2]
新建整数数组 res保存结果,整型变量 c保存进位,初始 c= 0.
将各个位上的数字相加,求出结果对应位上的数字和进位。
例如对个位计算: A[0] + B[0] = 7 + 8 = 15, 结果个位上是 5,进位是 1. 所以 res[0] = 5, 进位 c = 1
最后把结果数组 res 中就保存了计算倒序结果,倒序输出就是答案。
代码实现:O(n+m)
// 高精度加法
#include
#include
using namespace std;
vector add(vector &a, vector &b)
{
// c为进位
int c = 0;
vector res;
// 如果数组a和b有没遍历完的,进行循环
for (int i = 0; i < a.size() || i < b.size(); i++)
{
// 没遍历完的,加到进位中 此时c=a[i]+b[i]+c
if (i < a.size())
c += a[i];
if (i < b.size())
c += b[i];
// 结果只需要保存c对10的模
res.push_back(c % 10);
// c变为c/10 进位为1下次循环加
c /= 10;
}
// 如果数组全部遍历完,还需要考虑最高位是否有进位,若有则最高位+1
if (c)
res.push_back(1);
return res;
}
int main()
{
string n, m;
cin >> n >> m;
vector a, b;
// a,b都为字符串,可以遍历,将每个字符转为int 存入数组 为后续加法做准备
for (int i = n.size() - 1; i >= 0; i--)
a.push_back(n[i] - '0');
for (int i = m.size() - 1; i >= 0; i--)
b.push_back(m[i] - '0');
auto c = add(a, b);
// 输出结果
for (int i = c.size() - 1; i >= 0; i--)
cout << c[i];
return 0;
}
题目792:高精度减法

算法思想:
和高精度+法差不多,值得注意的是:
1、减法的借位处理,不管借不借位,都可以把(t+10)%10加进数组!
2、相减为负数的处理:先进行判断大小,保证减法都是大减小,最后考虑符号问题。
3、前导0的处理
代码实现:O(n)
#include
#include
#include
using namespace std;
// 判断a>=b
bool cmp(vector &a, vector &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];
// 相等返回true
return true;
}
vector sub(vector &a, vector &b)
{
vector res;
int t = 0;
// 减法从个位开始
for (int i = 0; i < a.size(); i++)
{
// t=0则 t=a[i] t=1则t=a[i]-1
t = a[i] - t;
// 如果被减数还有位数
if (i < b.size())
// t减去被减数
t -= b[i];
// t<0则t=10+t 借位 t>=0则t=t 不借位
res.push_back((t + 10) % 10);
// 借位则t=1 否则t=0
if (t < 0) t = 1;
else t = 0;
}
// 去除多余的0 003=3
while (res.size() > 1 && res.back() == 0) res.pop_back();
return res;
}
int main()
{
string n, m;
cin >> n >> m;
vector a, b;
//反向读取字符串
for (int i = n.size() - 1; i >= 0; i--)
a.push_back(n[i] - '0');
for (int i = m.size() - 1; i >= 0; i--)
b.push_back(m[i] - '0');
// 调用函数比大小
if (cmp(a, b))
{
auto c = sub(a, b);
for (int i = c.size() - 1; i >= 0; i--)
cout << c[i];
}
else
{
auto c = sub(b, a);
//带上-号
cout<<"-";
for (int i = c.size() - 1; i >= 0; i--)
cout << c[i];
}
return 0;
}
题目793:高精度乘法

算法思想:
和高精度+-法差不多,值得注意的是:
1、乘法的进位处理
2、特殊判断,如果×0的话,直接输出结果
3、注意最高位,最后一次乘完要判断t的大小,为1说明最高位有进位,手动添加进数组即可。
代码实现:O(n)
#include
#include
#include
using namespace std;
//高精度乘法
vector mul(vector& a,int b){
vector res;
//进位
int t=0;
//如果b为0,则结果为0 不必进行乘法运算
if(b==0) {
res.push_back(0);
return res;
}
//每一位都与b相乘
for(int i=0;i>a>>b;
vector 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--) cout<
题目794:高精度除法

算法思想:
和高精度+-×法差不多,值得注意的是:
1、除法比较特殊,需要从最高位开始除数,所以for循环倒序,因为最后一位存的是最高位。
2、因为除法存在第一位是0的情况,所以要去除前导0。
3、不懂得友友可以自己手算模拟一下!很清晰!

代码实现:O(n)
#include
#include
#include
#include
using namespace std;
vector div(vector &a, int b, int &r)
{
vector res;
// 除法需要从最高位开始算
for (int i = a.size() - 1; i >= 0; i--)
{
// 余数操作
r = r * 10 + a[i];
// 存入商
res.push_back(r / b);
// 更新余数
r = r % b;
}
// 反转数组 去除多余的前导0 因为除法第一个数一定是0
reverse(res.begin(), res.end());
while (res.size() > 1 && res.back() == 0)
res.pop_back();
return res;
}
int main()
{
string a;
int b;
cin >> a >> b;
vector A;
// 反转存入数组
for (int i = a.size() - 1; i >= 0; i--)
A.push_back(a[i] - '0');
// 余数
int r = 0;
auto c = div(A, b, r);
for (int i = c.size() - 1; i >= 0; i--)
cout << c[i];
cout << endl
<< r << endl;
return 0;
}
欢迎友友评论区讨论,有不足请指出,大家一起交流进步!
浙公网安备 33010602011771号