目录
高精度
分四种情况 大整数相加相减 大整数乘小整数 大整数除小整数
①大整数的存储 用数组存 A0存个位以此类推
②计算 用代码实现加法器功能
高精度加法
每次计算的过程就是算Ai+Bi+t //t代表进位 随时更新
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> add(vector<int> A,vector<int> B)
{
vector<int> C;
if(A.size()<B.size()) return add(B,A);
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(1);
return C;
}
int main()
{
string a,b;
vector<int> A,B;
cin>>a>>b; //"123456789"
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;
}
高精度减法
t用来判断上一位是否经历了借位 借位以后就减一
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> sub(vector<int> &A, vector<int> &B) // C = A - B, 满足A >= B, A >= 0, B >= 0
{
vector<int> C;
if(A.size()<B.size()) return sub(B,A);
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;
}
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;
}
int main()
{
string a,b;
vector<int> A,B;
cin>>a>>b; //"123456789"
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))
{
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;
}
高精度乘法
注 A为大整数 b为小整数
#include <iostream>
#include <cstring>
#include <algorithm>
#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=t+A[i]*b;
C.push_back(t%10);
t=t/10;
}
while(C.size()>1&&C.back()==0) C.pop_back();
return C;
}
int main()
{
string a;
int b;
vector<int> A;
cin>>a>>b; //"123456789"
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;
}
高精度除法
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> div(vector<int> &A, int b,int &r) // r为余数
{
vector<int> C;
r=0;
for(int i=A.size()-1;i>=0;i--)
{
r=r*10+A[i];
C.push_back(r/b);
r=r%b;
}
reverse(C.begin(),C.end());
while(C.size()>1&&C.back()==0) C.pop_back();
return C;
}
int main()
{
string a;
int b;
vector<int> A;
cin>>a>>b; //"123456789"
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;
return 0;
}
前缀和
普通前缀和
s[0]=0 为了后面的公式更统一 如 求1-2的和 结果就等于s2-s0 我们可以知道结果等于s2这里s0=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 <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int main()
{
int n,m,q;
cin>>n>>m>>q;
int s[N][N];
s[0][0]=0;
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <=m; j ++ )
{
scanf("%d",&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,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
cout<< s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]<<endl; //求子矩阵的和
}
return 0;
}
差分(前缀和的逆过程)
一维差分
为了让前缀和数组a[] 在l以后每一个都加c 只需要bl+c 由于每次都会加上这个元素 所以以后的a[i]每个都加了c
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int a[N],b[N]; //a是b的前缀和 b是a的前缀
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++)
scanf("%d", &a[i]);
for(int i=1;i<=n;i++)
insert(i,i,a[i]); //此处生成了最初的差分数组
// for(int i=1;i<=n;i++)
// printf("%d ",b[i]);
// cout<<endl;
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];
for(int i=1;i<=n;i++)
printf("%d ",b[i]);
return 0;
}
二维差分矩阵
调整方式 左上角的矩阵加上c 调整另外三块区域 如图
#include <iostream>
#include <cstring>
#include <algorithm>
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][y1]-=c;
b[x1][y2+1]-=c;
b[x2+1][y2+1]+=c; //减了两遍c加了一遍c为保持不变再加一次c
}
int main()
{
int n,m,q;
cin>>n>>m>>q;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
scanf("%d", &a[i][j]);
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
insert(i,j,i,j,a[i][j]); //形成了第一个差分矩阵
while(q--)
{
int x1,y1,x2,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-1][j]+b[i][j-1]-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;
}