高精度加法
#include<bits/stdc++.h>
using namespace std;
vector<int>add(vector<int>&A, vector<int>&B){
vector<int>C;
int t=0;
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);
return C;
}
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 /= 10;
}
if(t) C.push_back(t); // for(int i = 0; i < A.size() || t; i ++)
return C;
}
int main(){
string a,b; cin>>a>>b;
vector<int>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];
}
高精度减法
#include<bits/stdc++.h>
using namespace std;
bool cmp(vector<int>&A, vector<int>&B){
// A 是否>= 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;
}
// C = A - B
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;
}
while(C.size()>1 && C.back() == 0) C.pop_back();// 去掉数字前导的 0;
return C;
}
int main(){
string a,b; cin>>a>>b;
vector<int>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)){ // 如果 A >= B,计算 A - B
auto C = sub(A,B);
for(int i=C.size()-1; i>=0; i--) cout<<C[i];
}
else{ // 否则计算 B - A
cout<<'-';
auto C = sub(B,A);
for(int i=C.size()-1; i>=0; i--) cout<<C[i];
}
}
高精度乘法
#include<bits/stdc++.h>
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++){ // 要么 i 没循环结束,要么 t != 0, 加 t 的判断是为了放入最后一位数字
t += A[i] * B;
C.push_back(t%10);
t /= 10; //上一位进位
}
while(C.size()>1 && C.back()==0) C.pop_back();// 去掉数字前导的 0;
return C;
}
int main(){
string a; int B;
cin>>a>>B;
vector<int>A;
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];
}
高精度除法
#include<bits/stdc++.h>
using namespace std;
vector<int>div(vector<int>&A, int B, int &r){
// 注意除法从最高位开始计算
vector<int>C;
for(int i=A.size()-1; i>=0; i--){
r = r * 10 + A[i];// 竖式下拉
C.push_back(r/B); // 试除,可能会加入多个0
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;
cin>>a>>B;
vector<int>A;
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<<endl;
}
数组前缀和
// 下标从 1 开始, a[1], a[2],...,a[n]
#include<iostream>
using namespace std;
const int N=100010;
int a[N],s[N];
int main(){
// 数组前缀
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++) cin>>a[i], s[i] = s[i-1]+a[i];
while(q--){
int l, r;
cin>>l>>r;
cout<<s[r]-s[l-1]<<endl;
}
}
矩阵前缀和
前缀中动 ,差分中动 。
#include<iostream>
using namespace std;
const int N=1010;
int a[N][N], s[N][N];
int main(){
int m,n,q;cin>>m>>n>>q;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++){
cin>>a[i][j], s[i][j] = s[i][j-1]+s[i-1][j]-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;
}
}
数组差分——前缀和的逆运算
,构造 ,使得 。于是得差分数组:
是 的前缀和,对 求前缀和就可得到原数组(O(n))。
这类操作可以很好解决区间操作问题:给定一个区间,对区间中的元素进行操作,如加某个数。
差分核心:将 全部加 ,等价于 , ;
#include<iostream>
using namespace std;
const int N=100010;
int a[N],b[N];
void insert(int l, int r, int c){
// 原数组的[l,r]区间加 c,只需对差分数组操作就行。
b[l] += c;
b[r+1] -= c;
}
int main(){
int n,q; cin>>n>>q;
for(int i=1;i<=n;i++) cin>>a[i],insert(i,i,a[i]);// 构建
while(q--){
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]<<' ';
}
矩阵差分
给子矩阵加上一个数。
#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){
b[x1][y1] += c;
b[x1][y2+1] -=c;
b[x2+1][y1] -=c;
b[x2+1][y2+1] +=c;
}
int main(){
int m,n,q;cin>>m>>n>>q;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++){
cin>>a[i][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<=m;i++){
for(int j=1;j<=n;j++){
b[i][j] += b[i-1][j] +b[i][j-1] -b[i-1][j-1];
cout<<b[i][j]<<" ";
}
puts("");
}
}
Q.E.D.