【高精度&&前缀和&&差分】

目录

高精度

高精度加法

高精度减法

高精度乘法

 高精度除法

 前缀和

一维

二维

差分

一维

二维


高精度

高精度加法

#include<iostream>
#include<vector>
#include<string>

vector<int> add(vector<int> &A,vector<int> &B){
    int i,t=0;
    for(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(1);
    while(C.size()>1&&C.back()==0) C.pop_back();
    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');

    C=add(A,B);
    for(int i=C.size()-1;i>=0;i--) cout<<C[i];
    cout<<endl;
    return 0;
}

高精度减法

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

//判断是否有A>=B
bool cmp(vector<int> A,vector<int> B){
    if(A.size()!=B.size()) return A.size()>B.size();
    else{
        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){
    int i,t;
    vector<int> C;
    for(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,C;
    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');
    
    
    if(cmp(A,B)){
        C=sub(A,B);
        for(int i=C.size()-1;i>=0;i--) cout<<C[i];
    }
    else{
        C=sub(B,A);
        printf("-");
        for(int i=C.size()-1;i>=0;i--) cout<<C[i];
    }
    return 0;
}

高精度乘法

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

vector<int> mul(vector<int> A,int B){
    int t,i;
    vector<int> C;
    
    for(int i=0,t=0;i<A.size()||t!=0;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,b;
    int B=0;
    vector<int> A,C;
    
    cin>>a>>b;
    for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
    for(int i=0;i<b.size();i++) B=B*10+(b[i]-'0');
    
    C=mul(A,B);
    for(int i=C.size()-1;i>=0;i--) cout<<C[i];
    return 0;
}

 高精度除法

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

vector<int> div(vector<int> A,int B){
    int t,i;
    vector<int> C;
    for(i=0,t=0;i<A.size();i++){
        t=t*10+A[i];
        if(t==0) C.push_back(0),t=0;
        else{
            C.push_back(t/B);
            t%=B;
        }
    }
    C.push_back(t);
    return C;
}

int main(){
    string a,b;
    int B=0;
    vector<int> A,C;
    
    cin>>a>>b;
    for(int i=0;i<a.size();i++) A.push_back(a[i]-'0');
    for(int i=0;i<b.size();i++) B=B*10+(b[i]-'0');
    
    C=div(A,B);
    int i=0;
    while(C[i]==0&&i<C.size()-2) i++;
    for(;i<C.size()-1;i++) cout<<C[i];
    cout<<endl<<C[i];
    return 0;
}

 前缀和

顾名思义就是前缀的和

一维

主要代码:

s[0]=0;
for(int i=1;i<=n;i++){
    s[i]=s[i-1]+a[i-1];
}

为啥要构造嘞?

方便计算从l到r的和。试想加入l~r很长,且我们需要多组输入计算。这时候一个简单的式子就登场了

//原始算法
for(int i=l;i<=r;i++) sum+=a[i];
//使用前缀和
sum=s[r]-s[l-1];

 nia一个题

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

 注意:下标从1开始(因为s[i]=s[i-1]+a[i-1])

二维

简单画了一个图

一定要清楚,这是离散的数据

主要代码: 

 (看图理解)

//构造
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];

//应用
sum=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];

#include<iostream>
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>>a[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]+a[i][j];
        }
    }
    
    while(q--){
        int x1,y1,x2,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
void insert(int l,int r,int c){
    b[l]+=c;
    b[r]-=c;
}

然后理解一下,构造差分为什么只需要将a[i]分别插入

#include<iostream>
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,i;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++) scanf("%d",&a[i]);
	for(i=1;i<=n;i++) insert(i,i,a[i]);
	
	while(m--){
		int l,r,c;
		scanf("%d%d%d",&l,&r,&c);
		insert(l,r,c);
	}
	
	for(i=1;i<=n;i++) b[i]+=b[i-1];
	for(i=1;i<=n;i++) printf("%d ",b[i]); 
	return 0;
}

二维

感觉只要理解了上面以及数据是离散化的这两个点,也就蛮简单的了

 给指定区间加c

void insert(int x1,int y1,int x2,int y2,int c){
    b[x1][y1]+=c;
    b[x2+1][y1]-=c;
    b[x1][y2+1]-=c;
    b[x12][y2]+=c;
}

 

#include<iostream>
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){   //将给定区间加上c 
    b[x1][y1]+=c;
    b[x2+1][y1]-=c;
    b[x1][y2+1]-=c;
    b[x2+1][y2+1]+=c;

}

int main(){
    int n,m,q,i,j;
    scanf("%d%d%d",&n,&m,&q);

    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
    for(i=1;i<=n;i++)             //构造差分矩阵b 
        for(j=1;j<=m;j++)
            insert(i,j,i,j,a[i][j]);

    while(q--){
        int x1,y1,x2,y2,c;
        scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c);
        insert(x1,y1,x2,y2,c);
    }

    for(i=1;i<=n;i++){                     //计算b的前缀矩阵 
        for(j=1;j<=m;j++){        
            b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
        }
    }

    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++) printf("%d ",b[i][j]);
        printf("\n");
    }
    return 0;       
}

(质量太低而推荐受影响,我缺那点推荐吗??不过还是想好好完善一下啦) 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值