高精度(C++)——791、792、793、794

高精度加法

思路:将数反过来存储,从个位加起,用t来表示是否进位

模板:

#include<iostream>
#include<vector>
using namespace std;
int i;
vector<int> add(vector<int> &A,vector<int> &B)
{
    if(A.size()<B.size()) return add(B,A);//大的数字在前面,小的在后面
    int t=0;
    vector<int> c;
    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(t);//最后一位进位如果是1则直接在最前面写1,如果是0,则忽略不写
    return c;
}
int main()
{
    string a,b;
    vector<int> A,B;
    cin>>a>>b;
    for(int i=a.size-1;i>=0;i--)  A.push_back(a[i]-'0');//将a的数字顺序倒过来
    for(int i=b.size-1;i>=0;i--)  B.push_back(b[i]-'0');//将b的数字顺序倒过来
    auto c=add(A,B);//auto表示自动识别c的类型
    for(int i=c.size-1;i>=0;i++)  printf("%d ",c[i]);//将c的数字顺序倒过来,输出正确的结果c
    return 0;
}

例题791

题目:

给定两个正整数,计算它们的和。
输入格式
共两行,每行包含一个整数。
输出格式
共一行,包含所求的和。

答案

#include <iostream>
using namespace std;

const int N = 100010;
int A[N], B[N], C[N];

int Add(int a[], int b[], int c[], int cnt) {

    int t = 0;//t表示进位

    for (int i=1; i<=cnt; i++) {
        t += a[i] + b[i];    //进位加上a和b第i位上的数
        c[i] = t % 10;      //c的值就是进位的个位数
        t /= 10;      //把t的个位数去掉只剩下十位数,即只剩下这个位置的进位
    }
    if (t) c[++cnt] = 1;    //如果t==1,表示还有一个进位,要补上

    return cnt;
}

int main() {

    string a, b;
    cin >> a >> b;      //A和B倒着放进int数组,因为有进位,倒着放容易处理
    int cnt1 = 0;
    for (int i=a.size()-1; i>=0; i--)
        A[++cnt1] = a[i] - '0';

    int cnt2 = 0;
    for (int i=b.size()-1; i>=0; i--)
        B[++cnt2] = b[i] - '0';

    int tot = Add(A, B, C, max(cnt1, cnt2));  //因为A和B是倒着放的,所以C也要倒着输出
    for (int i=tot; i>=1; i--)
        cout << C[i];
}

例题792

题目

对两个大精度正整数做差,这里注意前后的数据处理0;
样例
输入
002
10


输出
-8

答案

#include <iostream>
#include <vector>
using namespace std;

const int N = 1000010;

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;
}

void trimZero(vector<int> &A)
{
    while (A.back() == 0 && A.size() > 1) A.pop_back();
}

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);
        if (t < 0) t = 1;
        else t = 0;
    }
    trimZero(C);

    return C;
}

int main()
{
    string a, b;
    cin >> a >> b;
    vector<int> A, B, C;
    for (int i = a.size() - 1; i >= 0; i--) A.push_back(a[i] - '0');
    for (int i = b.size() - 1; i >= 0; i--) B.push_back(b[i] - '0');

    trimZero(A), trimZero(B);

    if (cmp(A, B)) C = sub(A, B);
    else {
        C = sub(B, A);
        printf("-");
    }
    for (int i = C.size() - 1; i >= 0; i--) cout << C[i];

    return 0;
}
作者:goontry
链接:https://www.acwing.com/solution/content/2082/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

例题793

题目

给定两个正整数A和B,请你计算A * B的值。
输入格式
共两行,第一行包含整数A,第二行包含整数B。
输出格式
共一行,包含A * B的值。
数据范围
1≤A的长度≤100000,
1≤B≤10000

答案

#include <bits/stdc++.h>
#include <iostream>
#include <string.h>
using namespace std;

const int N = 100010;

int main()
{
    long long  b,la,i,t=0;
    char sa[N];
    scanf("%s",&sa);
    scanf("%ld",&b);
    int a[N],c[N];
    la=strlen(sa);

    //字符转数字,并倒叙存入  方便运算 
    for(i = la-1; i >= 0; i--)
        a[la-i-1]=sa[i]-'0'; 

    //如果乘的a数组结束或 或者暂存值的t结束了退出
    for(i=0;i<la||t;i++){
        //乘法是否结束
        if(i<la) t+=a[i]*b;
        //转存值
        c[i]=t%10;
        t/=10;
    }

    //去除前缀零   0023*0=0
    while(c[i-1]==0&&i>1)i--; 

    //输出结果
    for(int j=i-1;j>=0;j--) 
    printf("%d",c[j]);
    return 0;
}

例题794

题目

给定两个正整数A,B,请你计算 A / B的商和余数。
输入格式
共两行,第一行包含整数A,第二行包含整数B。
输出格式
共两行,第一行输出所求的商,第二行输出所求余数。
数据范围
1≤A的长度≤100000,
1≤B≤10000

答案

#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;
}

作者:过眼云烟1
链接:https://www.acwing.com/solution/content/2108/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值