/*
//Name: bigint.h
//Author:zgx(洛谷:zzwdsj)
//Date: 18/07/24 07:26
//Description:这个头文件中的bigint类为高精度数字类,
//机翻:The bigint class in this header file is a high-precision numeric class,
//可以处理int,long,long long,unsigned等基本类型的数字,也可以处理高精度数,并且可以处理负数。
//机翻:It can handle basic types of numbers such as int, long, long long, unsigned, high-precision numbers,
//and negative numbers.
*/
#ifndef BIGINT_H
#define BIGINT_H
/*引入头文件*/
#include<iostream>
#include<vector>
#include<utility>
/*高精度数字类*/
class bigint{
private:
std::vector<int> num;//用来存储数的绝对值
bool isNeg,isNumber;//isNeg表示是否是负数,isNumber表示是是合法的整数
public:
/*无参构造函数*/
bigint(){
num.clear();//清空
isNeg=false;//未赋值的数不是负数
isNumber=false;//未赋值的数不是一个合法的整数
}
/*处理进位*/
bigint& check(){
while(num.size()>1&&num.back()==0)num.pop_back();
if(num[0]==0&&num.size()==1)isNeg=false;
if(num.back()==0)return *this;//处理完之后直接返回自身
for(int i=1;i<num.size();i++){
num[i]+=num[i-1]/10;
num[i-1]%=10;
}
while(num.back()>=10){
num.push_back(num.back()/10);
num[num.size()-2]%=10;
}
return *this;//处理完之后直接返回自身
}
/*有符号类型构造函数*/
bigint(int x){//以int为入参的构造函数
num.clear();
if(x<0)x=-x,isNeg=true;//处理x是负数的情况
else isNeg=false;
int x2=x;
while(x2!=0){//将x的每一位分离
num.push_back(x2%10);
x2/=10;
}
isNumber=true;
if(x==0)num.push_back(0);
}
bigint(long x){//以long为入参的构造函数
num.clear();
if(x<0)x=-x,isNeg=true;
else isNeg=false;
long x2=x;
while(x2!=0){
num.push_back(x2%10);
x2/=10;
}
isNumber=true;
if(x==0)num.push_back(0);
}
bigint(long long x){//以long long为入参的构造函数
num.clear();
if(x<0)x=-x,isNeg=true;
else isNeg=false;
long long x2=x;
while(x2!=0){
num.push_back(x2%10);
x2/=10;
}
isNumber=true;
if(x==0)num.push_back(0);
}
/*无符号类型构造函数*/
bigint(unsigned x){//以unsigned为入参的构造函数
num.clear();
unsigned x2=x;
while(x2!=0){
num.push_back(x2%10);
x2/=10;
}
isNumber=true;
if(x==0)num.push_back(0);
}
bigint(unsigned long x){//以unsigned long为入参的构造函数
num.clear();
unsigned long x2=x;
while(x2!=0){
num.push_back(x2%10);
x2/=10;
}
isNumber=true;
if(x==0)num.push_back(0);
}
bigint(unsigned long long x){//以unsigned long long为入参的构造函数
num.clear();
unsigned long long x2=x;
while(x2!=0){
num.push_back(x2%10);
x2/=10;
}
isNumber=true;
if(x==0)num.push_back(0);
}
/*字符/字符串类型构造函数*/
bigint(char x){//以char为入参的构造函数存储x的ascll码
num.clear();
num.push_back(x);
check();
isNumber=true;
if(x==0)num.push_back(0);
}
bigint(std::string s){//以string为入参的构造函数存储s对应的整数
num.clear();
isNeg=false;
int leftIndex=0,i=s.size()-1;//如果前面有不合法的字符则去掉
while(s[leftIndex]>'9'||s[leftIndex]<'0'){
if(s[leftIndex]=='-')isNeg=!isNeg;
leftIndex++;
}
num.clear();//清空
bool flag=true;
for(i=s.size()-1;i>=leftIndex;i--){
if(s[i]>'9'||s[i]<'0'){
flag=false;
break;
}//处理s不合法的情况
num.push_back(s[i]-'0');
}
if(flag)isNumber=true;//如果s合法改变isNumber的值
}
/*重载正负号*/
bigint operator+(){
bigint res=*this;
return res;
}
bigint operator-(){
bigint res=*this;
res.isNeg=!res.isNeg;
return res;
}
/*绝对值*/
static bigint abs(bigint& x){//四则运算都会用到的绝对值函数
bigint res=x;
if(res.isNeg)return -res;
return +res;
}
/*声明友元*/
friend bigint operator+=(bigint&,bigint);friend bigint operator+(bigint,bigint);
friend bigint operator-=(bigint&,bigint);friend bigint operator-(bigint,bigint);
friend bigint operator*(bigint,bigint);friend bigint operator*=(bigint&,bigint);
friend bigint operator/(bigint,bigint);friend bigint operator/=(bigint&,bigint);
friend bigint operator%(bigint,bigint);friend bigint operator%=(bigint&,bigint);//将四则运算与模的重载声明为友元函数
friend bigint tobinary(bigint);friend bigint todecimal(bigint);//将十进制与二进制的互转声明为友元函数
friend bigint operator&(bigint,bigint);friend bigint operator&=(bigint&,bigint);
friend bigint operator|(bigint,bigint);friend bigint operator|=(bigint&,bigint);
friend bigint operator~(bigint);
friend bigint operator^(bigint,bigint);friend bigint operator^=(bigint&,bigint);
friend bigint operator<<(bigint,bigint);friend bigint operator<<=(bigint&,bigint);
friend bigint operator>>(bigint,bigint);friend bigint operator>>=(bigint&,bigint);//将位运算的重载声明为友元函数
friend std::ostream& operator<<(std::ostream&,const bigint&);//将输入输出的重载声明为友元函数
friend std::istream& operator>>(std::istream&,bigint&);
friend bool operator==(const bigint &a,const bigint &b);
friend bool operator!=(const bigint &a,const bigint &b);
friend bool operator<(const bigint &a,const bigint &b);
friend bool operator>(const bigint &a,const bigint &b);
friend bool operator<=(const bigint &a,const bigint &b);
friend bool operator>=(const bigint &a,const bigint &b);//将关系运算符的重载声明为友元函数
friend bool operator&&(const bigint &a,const bigint &b);
friend bool operator||(const bigint &a,const bigint &b);
friend bool operator!(const bigint &a);//将逻辑运算符的重载声明为友元函数
friend bigint qpow(bigint,bigint);//将快速幂声明为友元函数
protected:
friend bigint div(bigint,bigint,bool);
};
/*重载输入输出*/
std::istream& operator>>(std::istream& is,bigint& n)//重载输入
{
std::string s;
is>>s;
n.isNeg=false;
int leftIndex=0,i=s.size()-1;//如果前面有不合法的字符则去掉
while(s[leftIndex]>'9'||s[leftIndex]<'0'){
if(s[leftIndex]=='-')n.isNeg=!n.isNeg;
leftIndex++;
}
n.num.clear();//清空
bool flag=true;
for(i=s.size()-1;i>=leftIndex;i--){
if(s[i]>'9'||s[i]<'0'){
flag=false;
break;
}//处理s不合法的情况
n.num.push_back(s[i]-'0');
}
if(i<=leftIndex)n.isNumber=true;//如果s合法改变isNumber的值
return is;
}
std::ostream& operator<<(std::ostream& os,const bigint& n){ //重载输出
if(!n.isNumber)os<<"error";//如果n不是一个合法的数字输出"error"
else{
if(n.isNeg)os<<"-";//如果n是负数输出"-"
for(int i=n.num.size()-1;i>=0;i--)os<<n.num[i];//倒序输出
}
return os;
}
/*重载关系运算符*/
bool operator==(const bigint& a,const bigint& b){//重载==
if(a.num.size()!=b.num.size())return false;//如果位数不同则不等于
if(a.isNeg!=b.isNeg)return false;//如果符号不同则不等于
for(int i=a.num.size()-1;i>=0;i--)//逐位比较
if(a.num[i]!=b.num[i])return false;
return true;
}
bool operator!=(const bigint &a,const bigint &b){//重载!=
return !(a==b);
}
bool operator<(const bigint &a,const bigint &b){//重载<
if(a.isNeg||b.isNeg){//有负数单独判断
if(a.isNeg&&!b.isNeg)return true;//负数一定比正数小
if(!a.isNeg&&b.isNeg)return false;//正数移动比负数大
if(a.num.size()!=b.num.size())return a.num.size()>b.num.size();//位数不同则比较位数
for(int i=a.num.size()-1;i>=0;i--)//逐位比较
if(a.num[i]!=b.num[i])return a.num[i]>b.num[i];
}
else{
if(a.num.size()!=b.num.size())return a.num.size()<b.num.size();//位数不同则比较位数
for(int i=a.num.size()-1;i>=0;i--)//逐位比较
if(a.num[i]!=b.num[i])return a.num[i]<b.num[i];
}
return 0;
}
bool operator>(const bigint &a,const bigint &b){//重载<
return b<a;
}
bool operator<=(const bigint &a,const bigint &b){//重载<=
return !(a>b);
}
bool operator>=(const bigint &a,const bigint &b){//重载>=
return !(a<b);
}
/*重载逻辑运算符*/
bool operator&&(const bigint &a,const bigint &b){
return (a!=0)&&(b!=0);
}
bool operator||(const bigint &a,const bigint &b){
return (a!=0)||(b!=0);
}
bool operator!(const bigint &a){
return !(a!=0);
}
/*重载加*/
bigint operator+=(bigint &a,bigint b){//重载+=
if(!a.isNeg&&b.isNeg)return a=(a-=(-b));//正数a+负数b=a-(-b)
if(a.isNeg&&!b.isNeg)return a=(b-=(-a));//负数a+正数b=正数b+负数a=b-(-a)
if(a.num.size()<b.num.size())a.num.resize((int)b.num.size(),0);//如果不够位数补齐
for(int i=0;i!=b.num.size();i++)a.num[i]+=b.num[i];//逐位相加
return a.check();//处理进位
}
bigint operator+(bigint a,bigint b){//重载+
return a+=b;
}
/*重载减*/
bigint operator-=(bigint &a,bigint b){//重载-=
if(b.isNeg)return a=(a+(-b));//正数a-负数b=a+(-b)
if(a.isNeg)return a=-((-a)+b);//负数a-正数b=-((-a)+b)
if(a<b){//如果a<b则交换并且变号
bigint t;t=a;a=b;b=t;
a.isNeg=true;
}
if(a.num.size()<b.num.size())a.num.resize((int)b.num.size(),0);//如果不够位数补齐
for(int i=0;i!=b.num.size();i++){
a.num[i]-=b.num[i];//逐位相减
if(a.num[i]<0){//处理退位
a.num[i]+=10;
a.num[i+1]--;
}
}
return a.check();
}
bigint operator-(bigint a,bigint b){//重载-
return a-=b;
}
/*重载乘*/
bigint operator*(bigint a,bigint b){//重载*
bigint ans(0);//初始化存放答案的bigint类
if(a.isNeg==b.isNeg)ans.isNeg=false;//同号为正
else ans.isNeg=true;//异号为负
ans.num.resize((int)a.num.size()+b.num.size(),0);
for(int i=0;i<a.num.size();i++){
for(int j=0;j<b.num.size();j++){
ans.num[i+j]+=a.num[i]*b.num[j];
}
}
return ans.check();
}
bigint operator*=(bigint& a,bigint b){
return a=a*b;
}
/*重载除*/
bigint div(bigint a,bigint b,bool mode){//返回a除以b的商或余数
//初始化
bigint cur(0);//存储余数
bigint quo(0);//存储商
cur.num.pop_back();
quo.isNumber=true;
if(a.isNeg==b.isNeg)quo.isNeg=false;//同号为正
else quo.isNeg=true;//异号为负
cur.isNeg=a.isNeg;//在c+的int中余数一般与被除数同号
quo.num.resize((int)a.num.size(),0);//商的位数最多为被除数的位数
for(int i=a.num.size()-1;i>=0;i--){//从高位开始除
cur=cur*10+a.num[i];//余数进位
while(cur>=b){//如果余数大于等于除数
cur-=b;//减去除数
quo.num[i]++;//商加一
}
}
if(quo==0)quo.isNeg=false;
if(cur==0)cur.isNeg=false;
if(!mode)return quo.check();//如果mode为0则返回商
else return cur.check();//如果mode为1则返回余数
}
bigint operator/(bigint a,bigint b){//重载/
return div(a,b,0);
}
bigint operator/=(bigint& a,bigint b){//重载/=
return a=div(a,b,0);
}
bigint operator%(bigint a,bigint b){//重载%
return div(a,b,1);
}
bigint operator%=(bigint& a,bigint b){//重载%=
return a=div(a,b,1);
}
bigint operator++(bigint &a){//重载++(前置)
return a+=1;
}
bigint operator--(bigint &a){//重载--(前置)
return a-=1;
}
bigint operator++(bigint &a,int){//重载++(后置)
bigint t=a;
a+=1;
return t;
}
bigint operator--(bigint &a,int){//重载--(后置)
bigint t=a;
a-=1;
return t;
}
bigint tobinary(bigint a){//将a转换成二进制
bigint ret;//结果
ret.isNeg=a.isNeg;//二进制数与原数同号
ret.isNumber=a.isNumber;
while(a!=0){//倒取余数求二进制原码
ret.num.push_back(a.num[0]%2);
a/=2;
}
if(ret.isNeg){//如果是负数求反码+1
for(int i=0;i<ret.num.size();i++)ret.num[i]=!ret.num[i];//求反码
ret.num[0]++;//加一
int i=0;
while(ret.num[i]>1&&i+1<ret.num.size())ret.num[i+1]++,ret.num[i++]%=2;
if(ret.num.back()>1)ret.num.push_back(1),ret.num[ret.num.size()-2]=ret.num.back()%2;//处理进位
}
return ret;//由于二进制数以补码存储,不去前导零
}
bigint todecimal(bigint a){//将a转换成十进制
bigint res(0);//结果
if(a.isNeg){//如果是负数减一后求反码得到原码
a.num[0]--;//减一
int i=0;
while(res.num[i]<0)res.num[i+1]--,res.num[i++]+=2;
for(int i=0;i<a.num.size();i++)a.num[i]=!a.num[i];//处理退位
}
for(int i=a.num.size()-1;i>=0;i--)res=res*2+a.num[i];//转化成十进制
res.isNeg=a.isNeg;//十进制数与原数同号
return res.check();
}
/*重载位运算*/
bigint operator&(bigint a,bigint b){//重载&
a=tobinary(a);//将a转二进制
b=tobinary(b);//将b转二进制
bigint res=a;//最开始结果=a
if(!res.isNeg)res.num.resize((int)b.num.size(),0);//如果不够位正数补0,
else res.num.resize((int)b.num.size(),1);//负数补1
for(int i=0;i<res.num.size();i++)res.num[i]&=b.num[i];//逐位求与
res.isNeg&=b.isNeg;//符号位求与
res=todecimal(res);//转回十进制
return res.check();
}
bigint operator&=(bigint& a,bigint b){//重载&=
return a=a&b;
}
bigint operator|(bigint a,bigint b){//重载|
a=tobinary(a);//将a转二进制
b=tobinary(b);//将b转二进制
bigint res=a;//最开始结果=a
if(!res.isNeg)res.num.resize((int)b.num.size(),0);//如果不够位正数补0,
else res.num.resize((int)b.num.size(),1);//负数补1
for(int i=0;i<res.num.size();i++)res.num[i]|=b.num[i];//逐位求或
res.isNeg|=b.isNeg;//符号位求或
res=todecimal(res);//转回十进制
return res.check();
}
bigint operator|=(bigint& a,bigint b){//重载|=
return a=a|b;
}
bigint operator~(bigint a){//重载~
a=tobinary(a);//将a转二进制
bigint res=a;//最开始结果=a
for(int i=0;i<res.num.size();i++)res.num[i]=!res.num[i];//逐位取反
res.isNeg=!res.isNeg;//符号位取反
res=todecimal(res);//转回十进制
return res.check();
}
bigint operator^(bigint a,bigint b){//重载^
a=tobinary(a);//将a转二进制
b=tobinary(b);//将b转二进制
bigint res=a;//最开始结果=a
if(!res.isNeg)res.num.resize((int)b.num.size(),0);//如果不够位正数补0,
else res.num.resize((int)b.num.size(),1);//负数补1
for(int i=0;i<res.num.size();i++)res.num[i]^=b.num[i];;//逐位求异或
res.isNeg^=b.isNeg;//符号位求异或
res=todecimal(res);//转回十进制
return res.check();
}
bigint operator^=(bigint& a,bigint b){//重载^=
return a=a^b;
}
bigint qpow(bigint a,bigint b){//快速幂
bigint res=1;//结果
while(b!=0){
if(b.num[0]%2)res*=a;//这一位二进制是1则结果乘以a
a*=a;//a扩大
b/=2;//继续求下一位二进制
}
return res;
}
bigint operator<<(bigint a,bigint b){//重载<<
return a*qpow(2,b);//与a<<b等价
}
bigint operator<<=(bigint& a,bigint b){//重载<<=
return a=a<<b;
}
bigint operator>>(bigint a,bigint b){//重载>>
return a/qpow(2,b);//与a>>b等价
}
bigint operator>>=(bigint& a,bigint b){//重载>>=
return a=a>>b;
}
#endif
05-01
3697
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
12-12