Acwing 第一章 基础算法(二)

高精度加法:

                 什么是压位?

                               压位即为,一个空间内不仅限于存储0~9位置,可存储0~9999从而节省空间。

                注意事项:

                                1.auto是一种系统自动判别所属的数据类型,然后与之相对应

                                

#include <iostream>
#include <vector>

using namespace std;

vector<int> add (vector<int> &A,vector <int> &B)
{
    if(B.size() > A.size())   return add(B , A);
    vector<int> C;
    int t=0;
    for(int i=0 ;i<A.size() ;i++)
    {   
        t+=A[i];
        if(i<B.size())  t+=B[i];
        C.push_back(t%10);
        t=t/10;
    }
    
    if(t)   C.push_back(t);
    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');
    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--)    cout<<C[i];
    
    return 0;
}

高精度减法;

                        注意事项:

                                        1.借位只能是1或者0;

                                        2.注意最后的结果会有前导零

                                        3.注意结果的正负号

#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> sub(vector<int> &A, vector<int> &B)
{
    vector<int> C;
    for (int i = 0, t = 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;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();
    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');
    for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');

    vector<int> C;

    if (cmp(A, B)) C = sub(A, B);
    else C = sub(B, A), cout << '-';

    for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
    cout << endl;

    return 0;
}

                


高精度乘法:

                                注意事项:

                                                1.不要忘记最后的去除前导零

                                                2.当大数的高位运算完时,不要忽略t值,若不为零依然需要运算。

#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()
{   
    int b;string a;
    vector <int>    A;
    cin>>a>>b;
    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<<C[i];
    return 0;
}

高精度除法:

                注意事项:

                                1.开始容器逆序,所以在实际的除法运算中,要在容器末尾开始运算

                                2.最后得出的结果是依次进入容器,包括前导零,所以需要翻转去除

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

vector<int> div(vector<int> &A,int b,int &t)
{
    vector<int> C;
    t=0;
    for(int i=A.size()-1;i>=0;i--)
    {
        t=t*10+A[i];
        C.push_back(t/b);
        t=t%b;
    }
    reverse(C.begin(),C.end());
    while(C.size()>1&&C.back()==0) C.pop_back();
    return C;
}
int main()
{
    int b,m;string a;
    vector<int> A;
    cin>>a>>b;
    for(int i=a.size()-1;i>=0;i--)  A.push_back(a[i]-'0');
    auto C=div(A,b,m);
    for(int i=C.size()-1;i>=0;i--)  cout<<C[i];
    cout<<endl<<m;
    return 0;
}

前缀和差分:

        一维数组的前缀和:

                模板如下:

S[i] = a[1] + a[2] + ... a[i]
a[l] + ... + a[r] = S[r] - S[l - 1]

                例题如下:

#include <iostream>
using namespace std;
const int N=1e5+10;
int a[N],s[N];
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)    cin>>a[i],s[i]=s[i-1]+a[i];
    while(m--)
    {
        int l,r;
        cin>>l>>r;
        cout<<(s[r]-s[l-1])<<endl;
    }
    return 0;
}

        二维矩阵的前缀和:

                模板如下:

S[i, j] = 第i行j列格子左上部分所有元素的和
以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为:
S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]

                例题如下:

#include <iostream>
#include <vector>
using namespace std;
const int N=1010;
int a[N][N],s[N][N];
int main()
{
    int n,m,q;
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>s[i][j];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+s[i][j];
    
    while(q--)
    {
        int x1,x2,y1,y2;
        cin>>x1>>y1>>x2>>y2;
        cout<<(s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1])<<endl;
    }
    return 0;
}

         

        一维数组的差分:

                模板如下:

给区间[l, r]中的每个数加上c:B[l] += c, B[r + 1] -= c

                例题如下:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N=1e5+10;
int a[N],b[N];
void insert (int l,int r,int c)
{
    b[l]+=c;
    b[r+1]-=c;
}
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)   cin>>a[i],insert(i,i,a[i]);
    while(m--)
    {
        int l,r,c;
        cin>>l>>r>>c;
        insert(l,r,c);
    }
    for(int i=1;i<=n;i++)   b[i]+=b[i-1],cout<<b[i]<<" ";
    return 0;
}

        二维矩阵的差分:

                代码模板如下:

给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上c:
S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c

                例题如下:

// 3 4 3
// 1 2 2 1
// 3 2 2 1
// 1 1 1 1
// 1 1 2 2 1
// 1 3 2 3 2
// 3 1 3 4 1

// 2 3 4 1
// 4 3 4 1
// 2 2 2 2

//在输入前缀和矩阵的同时,生成差分矩阵。然后n次对差分矩阵进行修改,最后生成前缀和矩阵
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

const int N=1010;
int a[N][N],b[N][N];
void insert (int x1,int y1,int x2,int y2,int c)
{
    b[x1][y1]+=c;
    b[x2+1][y2+1]+=c;
    b[x2+1][y1]-=c;
    b[x1][y2+1]-=c;
}
int main()
{
    int n,m,e;
    cin>>n>>m>>e;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&a[i][j]),insert(i,j,i,j,a[i][j]);
    while(e--)
    {
        int x1,x2,y1,y2,c;
        cin>>x1>>y1>>x2>>y2>>c;
        insert(x1,y1,x2,y2,c);
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            b[i][j]+=b[i][j-1]+b[i-1][j]-b[i-1][j-1];
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++) cout<<b[i][j]<<" ";
        cout<<endl;
    }
        
           
           
    return 0;
}

                

双指针算法:

               两种形式:1.两个区间分别用两个指针指向 2.两个指针共同维护一个区间

                核心思想:对暴力做法优化到O(n);

for(int i=0;i<n;i++)
{
    while(j<i&&check(i,j)) J++;


    //每道题的具体逻辑
}

位运算:

                常见的两种操作:

                                1. n的二进制表示中第k位是几    n>>k&1

                                2.lowbit(x)操作,作用是返回x的最后一个1   x&-x

                理解补充:其中n>>k,位移运算,把第k位移动到最后一位,然后&1,求出最后一位

0 0 0 0 0 1 2 5 10        n>>k  运算

0 0 0 0 0 1 0 1  0         n>>k&1 运算 

int lowbit (int x) 
{
    return x & -x;
}

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aimigas

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值