1.高精度
c++中的sort是快排和插排的结合
sort(a,a+n);
c++中没有大整数类
1.常用类型
大整数位数<=106 a的大小<=10的9次方
- A-B
- A+B
- A/a
- A*a
2.思路
1.大整数存储:将大整数的每一位存在数组中
高位在前:低位在前?
低位在前(进位在末尾比较容易添加)
1.A+B:模拟手工算法的过程
Ai+Bi+进位
#include<vector>
const int N=1e6+10;//防止边界溢出
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;
}
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');//字符与数字的ascii码相差‘0’,低位先存
for(int i=a.size()-1;i>+0;i--) B.push_back(a[i]-'0');
auto c=add(A,B);//编译器自动推断类型
for(int i=0;i<c.size();i++) printf("%d",c[i]);
return 0;
}
2.A-B 手工模拟减法过程
Ai-Bi-t(借位
1.<0 Ai-Bi-t+10(借位
2.>=0 Ai-Bi-t
1.A>=B 直接算
2. A<B -(B-A)
//判断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)
{
// 已经确定A>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];//B[i]不为空时才减
c.push_back((t+10)%10);//将t大于0小于0合二为一了
if(t<0) t=1;//有借位
else t=0;//无借位
}
while(c.size()>0 && c.back()==0) c.pop.back();//高位为0是不需要输出的,如112-110=002;数组中是200,只用输出2即可,所以将数组末尾的0删去
}
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');//字符与数字的ascii码相差‘0’,低位先存
for(int i=a.size()-1;i>+0;i--) B.push_back(a[i]-'0');
if(cmp(A,B))
{
auto c=sub(A,B);//编译器自动推断类型
for(int i=0;i<c.size();i++) printf("%d",c[i]);
}
else
{
auto c=sub(B,A);//编译器自动推断类型
cout<<'-';
for(int i=0;i<c.size();i++) printf("%d",c[i]);
return 0;
}
A*b
思路
c[i]= (A[i]*b+t)%10//将b看作整体
t=(A[i]*b+t)/10 //进位
代码
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;
}
}
A/b
思路
Ci=(r10+Ai)/b
r=(r10+Ai)%b 高位余数
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%=b;
}
reverse(c,begin(),c.end());// 将数组翻转,和加减乘除输出一致
while(c.size()>0 && c.back()==0) c.pop.back();
return c;
}
2. 前缀和
描述:已知数组a1 a2 a3 …an 求前缀和 Si=a1+a2+a3+…+ai
下标从1开始 ,方便处理边界,统一公式,S[0]=0
思路
如何求Si=S[i-1]+ai
作用:快速求原数组一段的和,[l,r] 的和 = S[r]-S[l-1],时间是O(n)
代码
const int N=1e10;
int s[N];
for(int i=0;i<N;i++) s[i]=s[i-1]+a[i];
子矩阵和
- S[i, j] = 第i行j列格子左上部分所有元素的和:s[i][j]=s[i-1][j]+s[i][j-1]+a[i][j]
- 以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为:
S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]
3.差分
描述
已知数组 a1,a2,a3…an
构造b1,b2…bn 使得ai=b1+b2+…+bi,b数组就是a数组的差分
思路
b1=a1
b2=a2-a1
…
给数组A区间[l, r]中的每个数加上c:B[l] += c, B[r + 1] -= c
差分矩阵
给以(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