Y总基础算法课day2

高精度算法:

高精度加法的思想,高精度加法是为了计算长度非常长的数而存在的,比如计算的结果超过int型能表示的变量的时候,这时候就需要进行高精度加法的运算了,算法的思想是基于用数组去拆分原字符串的,从0-N分别从数的低为到高位这样方便低为的进位传入高位

#include <iostream>
#include <vector>

using namespace std;


vector<int> add(vector<int> &a,vector<int> &b)//高精度加法函数,穿入两个容器变量
{
    
    int c=0;//进位
    vector<int> tmp;//结果
    for(int i=0;i<a.size() || i<b.size();i++) 
    {
        if(i < a.size()) c += a[i];
        if(i < b.size()) c += b[i];
        //上述的是让上一位的进位加上这次的需要加的两个数
        tmp.push_back(c%10);//给结果的容器加入计算结果的个位
        c /= 10;//进位
    }
    if(c) tmp.push_back(1);//如果最后还有进位的话那就压入1
    return tmp;
}

int main(){
    //int n,m;
    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');//存入容器
    for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');//存入容器
    
    auto C= add(A,B);
    
    for(int i = C.size()-1;i>=0;i--) printf("%d",C[i]);
    return 0;
}

高精度减法:

高精度减法的计算和高精度加法的计算其实非常的类似,相比于高精度加法的进位而言,高精度减法就需要进行减法的借位,具体的算法如下

算法的核心是借位

t = a[i]-t

再判断一下是不是b[i]还有位数,然后t-=b[i]

判断此时的t是不是小于零接下来考虑借位

#include <iostream>
#include <vector>

using namespace std;



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


vector<int> subm(vector<int> &a,vector<int> &b){
    //int s=0;//错位
    //int c=0;
    vector<int> res;
    int t=0;
    for(int i=0;i< a.size();i++){
        t = a[i] - t;
        if(i<b.size()) t-=b[i];
        res.push_back((t+10)%10);
        if(t<0) t = 1;
        else t= 0;
    }

    
    while(res.size()>1 && res.back()==0)res.pop_back();
    
    return res;

};


int main(){
    
    string A,B;
    vector<int> a,b;
    
    cin >> A >> B;//输入字符串
    
    vector<int> 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');//加入容器内
    
    if(cmp(a,b)){//cmp函数用于判读前后数字的位置
        c = subm(a,b);//如果a>b那就让a-b
    }else{
        c= subm(b,a);//如果a<b调整相减的位置然后加个负号即可如3-5= -(5-3)
        printf("-");
    }
    //sub()
    for(int i =c.size()-1;i>=0;i--) printf("%d",c[i]);
    
    return 0;
}

高精度乘法,一阶

高精度乘法此处的话是用的长串乘上一个短的整形or无符号数,这样的话只需要计算每一位和这个短的数相乘的结果以及保存进位即可,相比于加法和减法而言更加简单,本次没有考虑计算结果的符号,需要判断只需要读取第一位,同正异负即可

#include <iostream>
#include <vector>

using namespace std;



vector<int> mul(vector<int> &a,int b){
    vector<int> res;//结果容器
    int t=0;
    for(int i=0;i< a.size();i++){
        t = b*a[i]+t; //上一次的进位加这一次的计算结果
        res.push_back(t%10);
        t = t/10;

    }

    
    if(t) res.push_back(t);
    
    return res;

};


int main(){
    
    string A;
    int B;
    vector<int> a;
    
    cin >> A >> B;//输入字符串
    
    vector<int> c;
    for(int i=A.size()-1; i>=0 ; i--) a.push_back(A[i]-'0');//保存长字符串
    
    
    c = mul(a,B);

    //sub()
    for(int i =c.size()-1;i>=0;i--) printf("%d",c[i]);
    
    return 0;
}

高精度除法

高精度的除法也是大数除上一个整数的,但是相比于人而言,计算机会更加的傻一些,它必须从最高位开始,步骤如下

1.保存当前长数组的最高位到0的位置

2.除不尽时如11/22那么就商为0,余数为1,接下来只需要让1*10+1到下一次的除法运算即可

3.直到计算到被除数的个数为止

算法的核心:余数*10加此高位

t=(t*10+a[i])/b[i]

#include <iostream>
#include <vector>

using namespace std;




vector<int> div(vector<int> &a,int b){
    vector<int> res;
    int t=0;//余数,用于保存最后的余数结果以及为下一次做准备
    for(int i=0;i< a.size();i++){

        int tmp  = (a[i] +t*10)/b;
        
        t = (a[i] + t*10)-tmp*b; //余数
        res.push_back(tmp%10);
        

    }


    printf("余数是%d\n",t);//有余数
    return res;

};


int main(){
    
    string A;
    int B;
    vector<int> a;
    
    cin >> A >> B;//读入数据
    
    vector<int> c;
    for(int i=A.size()-1; i>=0 ; i--) a.push_back(A[i]-'0');//读入容器中
    
    
    c = div(a,B);//a/B

    for(int i =c.size()-1;i>=0;i--) printf("%d",c[i]);
    
    return 0;
}

前缀和

前缀和的算法主要解决的问题:

1.数组中某一味到其后的位需要加一个固定的数

如a[n]=\sum_{n}^{b[i]},其中n=1,2,3,4...当需要a[5]-a[9]都加上10的时候,需要遍历一遍数组,需要O(n)的复杂度,但是由于是前缀和只需要让b[5]加上10,b[10]-10即可,因为a[i]是b[i]数组的前缀和,a[i]一定会受到前面b[i]的影响,同样在受影响之后的只需要重新减即可平衡了

差分数组的构造:b[i]

b[i] = a[i+1]-a[i]

#include <iostream>
#include <vector>

using namespace std;

#define N 1000010



int main(){
    
    int n,m;
    int a[N],sum[N];
    //vector<int> sum;
    
    cin >> n >> m;
    
    
    for(int i =1;i<=n;i++) {
        cin >> a[i];
        sum[1] = a[1];
        if(i>1) sum[i] = sum[i-1]+a[i];
    }
    //vector<int> c;
    for(int i=1;i<=m;i++){
        int s,e;
        cin >> s>>e;
        printf("%d\n",sum[e]-sum[s-1]);
    }


    return 0;
}

二维前缀和

二维前缀和最经典的公式

s[i][j] = s[i-1][j] +s[i][j-1] - s[i-1][j-1] + a[i][j];

区域的公式

res = s[x2][y2] -s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];

建议画个图理解一下,其实最难想的就是边界问题

#include <iostream>
#include <vector>

using namespace std;

#define N 1010

    
int n,m,q;//n行m列矩阵进行询问
int a[N][N];
int s[N][N];

int main(){

    cin >> n >> m>> q;

    for(int i =1;i<=n;i++) {
        for(int j =1;j<=m;j++){
            cin >> a[i][j]; 
            
            s[i][j] = s[i-1][j] +s[i][j-1] - s[i-1][j-1] + a[i][j];
        }
    }
    
    for(int i=1;i<=q;i++){
        int x1,y1,x2,y2;
        int res;
        cin >> x1>>y1>>x2>>y2;
        res = s[x2][y2] -s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];
        cout << res << endl;
    }
    
    return 0;
}
  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值