高精度模板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;
	}
};
posted @ 2023-03-08 12:44  A_zjzj  阅读(85)  评论(0编辑  收藏  举报