不走程序,直接上板子。
第一个板子压四位,支持带符号的加减乘。
第二个板子压九位,支持不带符号的四则运算和取模。
都封装了。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct intX
{
static const int M=600;
int xb[M+5];
intX& operator=(const char* c)
{
memset(xb,0,sizeof(xb));
int n=strlen(c),j=1,k=1;
for(int i=1;i<n;i++,k*=10)
{
if(k==10000) j++,k=1;
xb[j]+=k*(c[n-i]-'0');
}
xb[0]=j,xb[M]=c[0]-'0';
return *this;
}
intX& operator=(int a)
{
char s[25];
sprintf(s+1,"%d",a);
if(a<0) s[0]='1'; else s[0]='0';
return *this=s;
}
intX() {memset(xb,0,sizeof(xb)); xb[0]=1;}
intX(int n) {*this=n;}
bool operator>(const intX &b) const
{
if(xb[M]!=b.xb[M]) return xb[M]<b.xb[M];
if(xb[0]!=b.xb[0]) return xb[M]?xb[0]<b.xb[0]:xb[0]>b.xb[0];
for(int i=xb[0];i>0;i--)
if(xb[i]!=b.xb[i]) return xb[M]?xb[i]<b.xb[i]:xb[i]>b.xb[i];
return false;
}
bool operator<(const intX &b) const {return b>*this;}
bool operator<=(const intX &b) const {return !(*this>b);}
bool operator>=(const intX &b) const {return !(b>*this);}
bool operator!=(const intX &b) const {return b>*this||*this>b;}
bool operator==(const intX &b) const {return !(b>*this)&&!(*this>b);}
intX operator+(const intX &b) const
{
intX c,d=b,e=*this;
if(xb[M]^b.xb[M])
{
e.xb[M]=d.xb[M]=0;
c=e>d?e-d:d-e;
if((e>d&&xb[M]) || (e<d&&b.xb[M])) c.xb[M]=1;
return c;
}
c.xb[0]=max(xb[0],b.xb[0]), c.xb[M]=xb[M];
for(int i=1;i<=c.xb[0];i++)
{
c.xb[i]+=xb[i]+b.xb[i];
if(c.xb[i]>9999) c.xb[i]-=10000, c.xb[i+1]++;
}
if(c.xb[c.xb[0]+1]>0) c.xb[0]++;
return c;
}
intX operator-(const intX &b) const
{
intX c,d=b,e=*this;
if(e<0 && d<0) {d.xb[M]=e.xb[M]=0; return d-e;}
else if(d<0) {d.xb[M]=0; return d+e;}
else if(e<0) {d.xb[M]=1; return d+e;}
else if(e<d) {c=d-e; c.xb[M]=1; return c;}
c.xb[0]=xb[0];
for(int i=1;i<=c.xb[0];i++)
{
c.xb[i]+=xb[i]-b.xb[i];
if(c.xb[i]<0) c.xb[i]+=10000, c.xb[i+1]--;
}
while(!c.xb[c.xb[0]]&&c.xb[0]>1) c.xb[0]--;
return c;
}
intX& operator+=(const intX &b) {return *this=*this+b;}
intX& operator-=(const intX &b) {return *this=*this-b;}
intX operator*(const intX &b) const
{
intX c;
c.xb[0]=xb[0]+b.xb[0]+1;
for(int i=1;i<=xb[0];i++)
for(int j=1;j<=b.xb[0];j++)
c.xb[i+j-1]+=xb[i]*b.xb[j],
c.xb[i+j]+=c.xb[i+j-1]/10000,
c.xb[i+j-1]%=10000;
while(!c.xb[c.xb[0]] && c.xb[0]>1) c.xb[0]--;
if(*this!=0 && b!=0) c.xb[M]=xb[M]^b.xb[M];
return c;
}
intX operator*=(const intX &b) {return *this=*this*b;}
void readX(intX &b)
{
char s[2*M]; scanf("%s",s+1);
if(s[1]=='-') s[1]='0',s[0]='1'; else s[0]='0';
b=s;
}
void writeX()
{
if(xb[M]) printf("-");
printf("%d",xb[xb[0]]);
for(int i=xb[0]-1;i>0;i--)
printf("%04d",xb[i]);
}
};
int main()
{
intX a,b;
a.readX(a),b.readX(b);
(a+b).writeX();
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int LEN=10000+1,BIT=9;
struct intX
{
static const int MOD=1000000000;
long long s[LEN];
bool flag;
intX() {memset(s,0,sizeof(s)); s[0]=flag=1;}
intX& operator=(const char *num)
{
int l=strlen(num);
memset(s,0,sizeof(s));
for(int i=l-1;i>=0;i-=BIT)
{
++s[0];
long long w=1;
for(int j=i;j>i-BIT && j>=0;j--)
s[s[0]]+=(num[j]^48)*w, w*=10;
}
return *this;
}
intX& operator=(int num)
{
char a[LEN];
sprintf(a,"%d",num);
return *this=a;
}
intX(int n) {*this = n;}
intX(const char *n) {*this = n;}
bool operator>(const intX &a) const
{
if(s[0]!=a.s[0]) return s[0]>a.s[0];
int up=max(s[0],a.s[0]);
for(int i=0;i<up;i++)
if(s[up-i]!=a.s[up-i]) return s[up-i]>a.s[up-i];
return false;
}
bool operator<(const intX &a) const {return a>*this;}
bool operator<=(const intX &a) const {return !(*this>a);}
bool operator>=(const intX &a) const {return !(a>*this);}
bool operator!=(const intX &a) const {return a>*this||*this>a;}
bool operator==(const intX &a) const {return !(a>*this)&&!(*this>a);}
intX operator+(const intX &a) const
{
intX c;
int x=0;
c.s[0]=max(a.s[0],s[0])+1;
for(int i=1;i<=c.s[0];i++)
c.s[i]=a.s[i]+s[i]+x,
x=c.s[i]/MOD,
c.s[i]%=MOD;
while(c.s[c.s[0]]==0 && c.s[0]>1) c.s[0]--;
return c;
}
intX& operator+=(const intX &a) {return *this=*this+a;}
intX operator-(const intX &a) const
{
intX c;
c.s[0]=max(a.s[0],s[0])+1;
if(*this<a) c.flag=false;
for(int i=1;i<=c.s[0];i++)
{
if(c.flag) c.s[i]+=s[i]-a.s[i];
else c.s[i]+=a.s[i]-s[i];
if(c.s[i]<0) c.s[i]+=MOD, c.s[i+1]--;
}
while(c.s[c.s[0]]==0 && c.s[0]>1) c.s[0]--;
return c;
}
intX& operator-=(const intX &a) {return *this=*this-a;}
intX operator*(const intX &a) const
{
intX c;
c.s[0]=s[0]+a.s[0];
for(int i=1;i<=s[0];i++)
{
int x=0;
for(int j=1;j<=a.s[0];j++)
c.s[i+j-1]+=s[i]*a.s[j]+x,
x=c.s[i+j-1]/MOD,
c.s[i+j-1]%=MOD;
c.s[i+a.s[0]]=x;
}
while(c.s[c.s[0]]>0) c.s[0]++;
while(c.s[c.s[0]]==0 && c.s[0]>1) c.s[0]--;
return c;
}
intX& operator*=(const intX &a) {return *this=*this*a;}
intX operator<<(const int &num)
{
s[0]++;
for(int i=1;i<=s[0];i++)
{
s[i]<<=num;
if(s[i-1]>=MOD) s[i-1]-=MOD, ++s[i];
}
while(s[s[0]]==0 && s[0]>1) s[0]--;
return *this;
}
intX operator>>(const int &num)
{
for(int i=s[0];i>=1;i--)
{
if((s[i]&1) && i>1) s[i-1]+=MOD;
s[i]>>=num;
}
while(s[s[0]]==0 && s[0]>1) s[0]--;
return *this;
}
intX operator/(const intX &k) const
{
intX c=*this,tmp,lt,a;
a=k;
tmp.s[1]=1;
while(c>=a) a=a<<1,tmp=tmp<<1;
while(tmp.s[0]>1 || tmp.s[1])
{
if(c>=a) c-=a, lt+=tmp;
a=a>>1, tmp=tmp>>1;
}
c=lt;
while(c.s[c.s[0]]==0 && c.s[0]>1) c.s[0]--;
if(c.s[0]<1) c.s[c.s[0]=1]=0;
return c;
}
intX& operator/=(const intX &a) {return *this=*this/a;}
intX operator%(const intX &a) const {return *this-*this/a*a;}
intX& operator%=(const intX &a) {return *this=*this%a;}
};
ostream& operator<<(ostream &out,const intX &a)
{
if(!a.flag) putchar('-');
printf("%lld",a.s[a.s[0]]);
for(int i=a.s[0]-1;i>=1;i--)
printf("%0*lld",BIT,a.s[i]);
return out;
}
istream& operator>>(istream &in,intX &a)
{
char str[LEN];
scanf("%s",str);
a=str;
return in;
}
UPD:距离第一次写就这篇文章已有5个月,在此期间遇到了很多需要高精的题,才发现之前的模板有很多的缺陷,压位和多种运算固然不错,但独立性太差,码量过多与基于自损相减的除法运算复杂度过高还是硬伤,于是这次更新了新的Wint
。
新的写法基于vector
实现,码量--,除法换成了高精除低精,并且各运算相对独立,在实际应用中表现更好。
#include <cstdio>
#include <vector>
#include <algorithm>
struct Wint:vector<int>
{
Wint(int n=0) {push_back(n);check();}
Wint& check()
{
while(!empty()&&!back()) pop_back();
if(empty()) return *this;
for(int i=1;i<size();++i)
(*this)[i]+=(*this)[i-1]/10,
(*this)[i-1]%=10;
while(back()>=10)
{
push_back(back()/10);
(*this)[size()-2]%=10;
}
return *this;
}
};
bool operator!=(const Wint &a,const Wint &b)
{
if(a.size()!=b.size()) return 1;
for(int i=a.size()-1;i>=0;--i)
if(a[i]!=b[i]) return 1;
return 0;
}
bool operator==(const Wint &a,const Wint &b) {return !(a!=b);}
bool operator<(const Wint &a,const Wint &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 0;
}
bool operator>(const Wint &a,const Wint &b) {return b<a;}
bool operator<=(const Wint &a,const Wint &b) {return !(a>b);}
bool operator>=(const Wint &a,const Wint &b) {return !(a<b);}
Wint& operator+=(Wint &a,const Wint &b)
{
if(a.size()<b.size()) a.resize(b.size());
for(int i=0;i<b.size();++i) a[i]+=b[i];
return a.check();
}
Wint operator+(Wint a,const Wint &b) {return a+=b;}
Wint& operator-=(Wint &a,Wint b)
{
if(a<b) swap(a,b);
for(int i=0;i<b.size();a[i]-=b[i],++i)
if(a[i]<b[i])
{
int j=i+1;
while(!a[j]) ++j;
while(j>i) --a[j],a[--j]+=10;
}
return a.check();
}
Wint operator-(Wint a,const Wint &b) {return a-=b;}
Wint operator*(const Wint &a,const Wint &b)
{
Wint n;
n.assign(a.size()+b.size()-1,0);
for(int i=0;i<a.size();++i)
for(int j=0;j<b.size();++j)
n[i+j]+=a[i]*b[j];
return n.check();
}
Wint& operator*=(Wint &a,const Wint &b) {return a=a*b;}
Wint operator/(Wint a,const int &b)
{
Wint n; bool wp=0;
for(int i=a.size()-1,t=0;i>=0;--i)
{
t=t*10+a[i];
if(wp||t/b) wp=1,n.push_back(t/b);
t%=b;
}
reverse(n.begin(),n.end());
return n;
}
Wint& operator/=(Wint &a,const int &b) {return a=a/b;}
void readX(Wint &n)
{
char s[1000]; scanf("%s",s); n.clear();
for(int i=strlen(s)-1;i>=0;--i) n.push_back(s[i]-'0');
}
void writeX(Wint n)
{
if(n.empty()) putchar('0');
for(int i=n.size()-1;i>=0;--i) putchar(n[i]+'0');
}
UPD2:又经过了许久,我的高精度最终版终于诞生(怎么这么中二)。
新版在之前的Wint
基础上再改良,变成了压 9 位的高精,用vector
也不怕被卡了!
为了与压位相匹配,实现了新的赋值函数,支持大整数读入。
我持续了半年的伟业终于完成(
typedef long long ll;
struct Wint:vector<ll>
{
const static ll BIT=1e9;
Wint(ll n=0) {push_back(n);check();}
Wint& operator=(const char* num)
{
int Len=strlen(num)-1; clear();
for(int i=Len;i>=0;i-=9)
{
push_back(0); ll w=1;
for(int j=i;j>i-9&&j>=0;--j)
back()+=(num[j]^48)*w,w*=10;
}
return *this;
}
Wint& check()
{
while(!empty()&&!back()) pop_back();
if(empty()) return *this;
for(int i=1;i<size();++i)
(*this)[i]+=(*this)[i-1]/BIT,
(*this)[i-1]%=BIT;
while(back()>=BIT)
{
push_back(back()/BIT);
(*this)[size()-2]%=BIT;
}
return *this;
}
};
bool operator<(Wint a,Wint 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 0;
}
bool operator>(Wint a,Wint b) {return b<a;}
bool operator<=(Wint a,Wint b) {return !(a>b);}
bool operator>=(Wint a,Wint b) {return !(a<b);}
bool operator!=(Wint a,Wint b) {return a<b||b<a;}
bool operator==(Wint a,Wint b) {return !(a<b)&&!(b<a);}
Wint& operator+=(Wint &a,Wint b)
{
if(a.size()<b.size()) a.resize(b.size());
for(int i=0;i<b.size();++i) a[i]+=b[i];
return a.check();
}
Wint operator+(Wint a,Wint b) {return a+=b;}
Wint& operator-=(Wint &a,Wint b)
{
for(int i=0;i<b.size();a[i]-=b[i],++i)
if(a[i]<b[i])
{
int j=i+1;
while(!a[j]) ++j;
while(j>i) --a[j],a[--j]+=Wint::BIT;
}
return a.check();
}
Wint operator-(Wint a,Wint b) {return a-=b;}
Wint operator*(Wint a,Wint b)
{
if(a.empty()&&b.empty()) return a;
Wint n; n.assign(a.size()+b.size()-1,0);
for(int i=0;i<a.size();++i)
for(int j=0;j<b.size();++j)
n[i+j]+=a[i]*b[j];
return n.check();
}
Wint& operator*=(Wint &a,Wint b) {return a=a*b;}
Wint operator/(Wint a,int b)
{
Wint n; bool wp=0; ll t=0;
for(int i=a.size()-1;i>=0;--i)
{
t=t*Wint::BIT+a[i];
if(wp||t/b) wp=1,n.push_back(t/b);
t%=b;
}
reverse(n.begin(),n.end());
return n;
}
Wint& operator/=(Wint &a,int b) {return a=a/b;}
void readX(Wint &n) {char s[1000]; scanf("%s",s); n=s;}
void writeX(Wint n)
{
if(n.empty()) {putchar('0'); return;}
int Len=n.size()-1; printf("%lld",n[Len]);
for(int i=Len-1;i>=0;--i) printf("%09lld",n[i]);
}