高精度模板2--zhengjun
只支持非负数,用 vectoer 实现。
upd(2023.12.01): 增加了 bign mod ll 的功能,修复了 string to bign 的 bug。
upd(2023.12.05): 优化了大数相乘,复杂度为 \(\Theta(n^{log_23})\)。
using ull=unsigned long long;
using bigint=__int128;
using bigbig=__int128;
struct bign{
static const int block=16;
static const ull base=pow(10,block);
vector<ull>a;
bign():a(vector<ull>()){}
bign(ull x){
for(;x;x/=base)a.push_back(x%base);
}
bign(string s){
reverse(s.begin(),s.end());
for(int i=0;i<(int)s.length();i+=block){
int r=min((int)s.length(),i+block);
ull x=0;
for(int j=r-1;j>=i;j--)x=x*10+s[j]-48;
a.push_back(x);
}
}
bign operator = (ull x){
return *this=bign(x);
}
bign operator = (string s){
return *this=bign(s);
}
void resize(int len){
a.assign(len,0);
}
ull operator [] (const int &x)const{
return a[x];
}
ull& operator [] (const int &x){
return a[x];
}
friend istream& operator >> (istream& in,bign &x){
string s;
in>>s,x=s;
return in;
}
friend ostream& operator << (ostream& out,const bign &x){
if(x.a.empty())out<<"0";
else{
ull ed=x.a.back();
printf("%llu",ed);
for(int i=x.a.size()-2;~i;i--)printf("%0*llu",block,x[i]);
}
return out;
}
bool operator < (const bign &x)const{
if(a.size()!=x.a.size())return a.size()<x.a.size();
for(int i=a.size()-1;~i;i--)if(a[i]^x[i])return a[i]<x[i];
return 0;
}
bool operator == (const bign &x)const{
if(a.size()!=x.a.size())return 0;
for(int i=0;i<(int)a.size();i++)if(a[i]^x[i])return 0;
return 1;
}
bool operator != (const bign &x)const{
return !(*this==x);
}
bool operator > (const bign &x)const{
return x<*this;
}
bool operator <= (const bign &x)const{
if(a.size()!=x.a.size())return a.size()<x.a.size();
for(int i=a.size()-1;~i;i--)if(a[i]^x[i])return a[i]<x[i];
return 1;
}
bool operator >= (const bign &x)const{
return x<=*this;
}
bign operator += (const bign &x){
ull r=0;
for(int i=0;i<(int)x.a.size()||r;i++){
if(i<(int)x.a.size())r+=x[i];
if(i>=(int)a.size())a.push_back(0);
if((a[i]+=r)>=base)r=1,a[i]-=base;
else r=0;
}
return *this;
}
bign operator + (const bign &x)const{
bign t=*this;
return t+=x;
}
bign operator -= (const bign &x){
ull r=0;
for(int i=0;i<(int)x.a.size()||r;i++){
if(i<(int)x.a.size())r+=x[i];
if(a[i]>=r)a[i]-=r,r=0;
else a[i]+=base-r,r=1;
}
for(;!a.empty()&&!a.back();)a.pop_back();
return *this;
}
bign operator - (const bign &x)const{
bign t=*this;
return t-=x;
}
bign operator -= (const ull &_x){
ull r=0;
ull x=_x;
for(int i=0;x||r;i++){
r+=x%base,x/=base;
if(a[i]>=r)a[i]-=r,r=0;
else a[i]+=base-r,r=1;
}
for(;!a.empty()&&!a.back();)a.pop_back();
return *this;
}
bign operator - (const ull &x)const{
bign t=*this;
return t-=x;
}
friend void reduce(bign &a){
for(;!a.a.empty()&&!a.a.back();a.a.pop_back());
}
friend void split(const bign &a,bign &x,bign &y,int mid){
int len=min(mid,(int)a.a.size());
y.resize(len);
for(int i=0;i<len;i++)y[i]=a[i];
len=max(0,(int)a.a.size()-mid);
x.resize(len);
for(int i=0;i<len;i++)x[i]=a[mid+i];
reduce(x),reduce(y);
}
friend bign mul(const bign &a,int x){
if(a.a.empty())return bign();
bign b;
b.resize(a.a.size()+x);
for(int i=a.a.size()-1;~i;i--)b[i+x]=a[i];
return b;
}
bign operator * (const bign &x)const{
if(a.size()<=20&&x.a.size()<=20){
int len=a.size()+x.a.size()+1;
vector<bigbig>t(a.size()+x.a.size()+1);
for(int i=0;i<(int)a.size();i++)for(int j=0;j<(int)x.a.size();j++){
int k=i+j;
t[k]+=(bigbig)a[i]*x[j],t[k+1]+=t[k]/base,t[k]%=base;
}
bign ans;
ans.resize(len);
for(int i=0;i<(int)t.size();i++){
if(i+1<(int)t.size())t[i+1]+=t[i]/base;
ans[i]=t[i]%base;
}
reduce(ans);
return ans;
}
int mid=(max(a.size(),x.a.size())+1)/2;
bign A,B,C,D;
split(*this,A,B,mid);
split(x,C,D,mid);
bign ac=A*C,bd=B*D,t=(A+B)*(C+D)-ac-bd;
return mul(ac,mid*2)+mul(t,mid)+bd;
}
bign operator *= (const bign &x){
return *this=*this*x;
}
bign operator *= (const int &x){
bigint r=0;
for(int i=0;i<(int)a.size()||r;i++){
if(i>=(int)a.size())a.push_back(0);
r+=x*(bigint)a[i],a[i]=r%base,r/=base;
}
return *this;
}
bign operator * (const int &x)const{
bign t=*this;
return t*=x;
}
bign operator *= (const ull &x){
bigint r=0;
for(int i=0;i<(int)a.size()||r;i++){
if(i>=(int)a.size())a.push_back(0);
r+=x*(bigint)a[i],a[i]=r%base,r/=base;
}
return *this;
}
bign operator * (const ull &x)const{
bign t=*this;
return t*=x;
}
bign operator /= (const ull &x){
bigint r=0;
for(int i=a.size()-1;~i;i--){
r=r*base+a[i];
a[i]=r/x,r%=x;
}
for(;!a.empty()&&!a.back();)a.pop_back();
return *this;
}
bign operator / (const ull &x)const{
bign t=*this;
return t/=x;
}
friend bign qpow(const bign &_x,const ull &_y){
bign x(_x),ans(1);
for(ull y=_y;y;y>>=1,x*=x)if(y&1)ans*=x;
return ans;
}
ull trans()const{
ull x=0;
for(int i=a.size()-1;~i;i--)x=x*base+a[i];
return x;
}
ull operator % (const ull &x)const{
ull res=0;
for(int i=a.size()-1;~i;i--){
res=((bigbig)res*base+a[i])%x;
}
return res;
}
};