高精度类。。可进行有符号加减乘除取余。。以及+-*/%<<>>==><运算符。。可修改进制(2到10000)。。
#define refcnt(a) while((a).cells[(a).ccount]==0&&(a).ccount>0)(a).ccount--;
const int cellcount=1100,cellwidth=1;//精确到cellcount*cellwidth位
int base=10;//进制
struct bigint
{
int cells[cellcount+1];
int ccount;
bool op;
bigint()
{
op=true;
memset(cells,0,sizeof(cells));
ccount=0;
}
bigint(int v)
{
op=true;
if(v<0){v=-v;op=false;}
memset(cells,0,sizeof(cells));
cells[0]=v;
ccount=0;
while(cells[ccount]>=base){
cells[ccount+1]=cells[ccount]/base;
cells[ccount]%=base;
ccount++;
}
}
inline void _parse(char* ch,int p,int& cp)
{
for(int i=p;i<p+cellwidth;i++)
cp=cp*10+ch[i]-'0';
}
void parse(char* ch)
{
if(ch[0]=='-'){
op=false;
ch++;
}else
op=true;
int l=strlen(ch);
int i,j,k;
for(i=l-cellwidth,j=0;i>=0;i-=cellwidth)
_parse(ch,i,cells[j++]);
if(i!=-cellwidth){
for(k=0;k<i+cellwidth;k++)
cells[j]=cells[j]*10+ch[k]-'0';
ccount=j;
}
else ccount=j-1;
}
friend istream& operator>>(istream& stream,bigint& num)
{
char buff[10000];
stream>>buff;
memset(num.cells,0,sizeof(int)*(num.ccount+1));
num.ccount=0;
num.parse(buff);
return stream;
}
void output(char* res) const
{
char* r=res;
if(!op&&(ccount!=0||cells[0]!=0))*(res++)='-';
sprintf(res,"%d",cells[ccount]);
res+=strlen(res);
char format[5]="%00d";
format[2]='0'+cellwidth;
for(int i=ccount-1;i>=0;i--){
sprintf(res,format,cells[i]);
res+=cellwidth;
}
res=r;
}
friend ostream& operator<<(ostream& stream,const bigint& num)
{
char buff[cellcount*cellwidth+1];
num.output(buff);
stream<<buff;
return stream;
}
inline static int cmp(const bigint& a,const bigint& b,bool ignore=false)
{
int r=1;
if(!ignore){
if(a.op^b.op)return a.op?1:-1;
if(!(a.op^b.op)&&!a.op) r=-1;
}
if(a.ccount>b.ccount)return r;
else if(a.ccount<b.ccount)return -r;
else
{
for(int i=a.ccount;i>=0;i--){
if(a.cells[i]>b.cells[i])return r;
else if(a.cells[i]<b.cells[i])return -r;
}
}
return 0;
}
bool operator <(const bigint& a) const
{
return cmp(*this,a)<0;
}
bool operator >(const bigint& a) const
{
return cmp(*this,a)>0;
}
bool operator ==(const bigint& a) const
{
return cmp(*this,a)==0;
}
inline static void getplus(bigint& res,const bigint& a,const bigint& b,bool op=true)
{
res.op=op;
int up=0;
int tmp;
res.ccount=min(max(a.ccount,b.ccount)+1,cellcount);
memset(res.cells,0,sizeof(res.cells));
for(int i=0;i<res.ccount;i++)
{
res.cells[i]=(tmp=res.cells[i]+a.cells[i]+b.cells[i])%base;
res.cells[i+1]=tmp/base;
}
refcnt(res);
}
inline static void getminus(bigint& res,const bigint& a,const bigint& b,bool op=true)
{
if(cmp(a,b,true)<0){
getminus(res,b,a,!op);return;}
res.op=op;
int up=0;
int tmp;
res.ccount=a.ccount;
memset(res.cells,0,sizeof(res.cells));
for(int i=0;i<=res.ccount;i++)
{
if((tmp=res.cells[i]+a.cells[i]-b.cells[i])<0){tmp+=base;res.cells[i+1]--;}
res.cells[i]=tmp;
}
refcnt(res);
}
inline static void getmultiply(bigint& res,const bigint& a,const bigint& b,int offset=0)
{
res.op=!(a.op^b.op);
int up=0;
int tmp;
res.ccount=min(a.ccount+b.ccount+1+offset,cellcount);
memset(res.cells,0,sizeof(res.cells));
for(int i=0;i<=a.ccount;i++)
for(int j=0;j<=b.ccount;j++)
{
if(i+j+offset>=cellcount)break;
res.cells[i+j+offset]=(tmp=res.cells[i+j]+a.cells[i]*b.cells[j])%base;
res.cells[i+j+1+offset]+=tmp/base;
}
refcnt(res);
}
inline static void getmultiply(bigint&res,const bigint&a,int b,int offset=0)
{
res.op=a.op;
if(b<0){res.op=!res.op;b=-b;}
int up=0;
int tmp=0;
int i;
memset(res.cells,0,sizeof(res.cells));
for(i=0;i<=a.ccount||tmp!=0;i++)
{
if(i+offset>=cellcount)break;
res.cells[i+offset]=(tmp=res.cells[i+offset]+a.cells[i]*b)%base;
res.cells[i+1+offset]=tmp/base;
}
res.ccount=i+offset;
refcnt(res);
}
bigint operator -() const
{
bigint res=*this;
if(cells[0]==0&&ccount==0)return res;
else {
res.op=!res.op;
return res;
}
}
bigint operator +(const bigint& a) const
{
bigint res(0);
if(!(op^a.op))
getplus(res,*this,a,op);
else
getminus(res,*this,a,op);
return res;
}
bigint operator -(const bigint& a) const
{
bigint res(0);
if(!(a.op^op))
getminus(res,*this,a,op);
else
getplus(res,*this,a,op);
return res;
}
bigint operator *(const bigint& a) const
{
bigint res(0);
getmultiply(res,*this,a);
return res;
}
bigint operator *(int a) const
{
bigint res;
getmultiply(res,*this,a);
return res;
}
inline static void tryminus(bigint& res,bigint& a,const bigint& b)
{
int ai,bi=b.cells[b.ccount],pre=a.ccount-b.ccount;
if(a.cells[a.ccount]>b.cells[b.ccount])ai=a.cells[a.ccount]/(b.cells[b.ccount]+1);
else{
if(a.ccount==b.ccount&&a.cells[a.ccount]==b.cells[b.ccount]){
res.cells[0]++;
a=a-b;
return;
}
ai=(a.cells[a.ccount]*base+a.cells[a.ccount-1])/(b.cells[b.ccount]+1);
pre--;
}
res.cells[pre]+=ai;
bigint r;
getmultiply(r,b,ai,pre);
bigint an;
getminus(an,a,r);
a=an;
}
inline static void make(bigint& r)
{
refcnt(r);
for(int i=0;i<=r.ccount;i++)
if(r.cells[i]>=base)
{
r.cells[i+1]+=r.cells[i]/base;
r.cells[i]%=base;
}
if(r.cells[r.ccount+1]>0)r.ccount++;
while(r.cells[r.ccount]>=base&&r.ccount<=cellcount){
r.cells[r.ccount+1]+=r.cells[r.ccount]/base;
r.cells[r.ccount]%=base;
r.ccount++;
}
}
inline static bool getdevide(bigint& res,bigint& ys,const bigint& a,const bigint& b)
{
if(b.cells[0]==0&&b.ccount==0)return false;
res.ccount=a.ccount;
memset(res.cells,0,sizeof(res.cells));
memcpy(&ys,&a,sizeof(bigint));
while(true)
{
int c=cmp(ys,b,true);
if(c<0)break;
if(c==0){memset(&ys,0,sizeof(ys));res.cells[0]++;break;}
else
{
tryminus(res,ys,b);
}
}
make(res);
return true;
}
bigint operator %(const bigint& a) const
{
bigint res,ys;
getdevide(res,ys,*this,a);
ys.op=op;
return ys;
}
bigint operator /(const bigint& a) const
{
bigint res,ys;
getdevide(res,ys,*this,a);
res.op=!(op^a.op);
return res;
}
};