板子

板子

高精

namespace BIG_num{
	using cpx=complex<double>; const double PI=acos(-1); vector<cpx>roots= {{0,0},{1,0}};
	void ensure_capacity(int min_capacity) {
		for(int len=roots.size();len<min_capacity;len*=2) for(int i=len>>1; i<len; i++) {
			roots.emplace_back(roots[i]); double angle=2*PI*(2*i+1-len)/(len*2);
			roots.emplace_back(cos(angle),sin(angle));
		}
	}
	void fft(vector<cpx>&z,bool inverse) {
		int n=z.size(); ensure_capacity(n);
		for(int i=1,j=0;i<n;i++){int BIGt=n>>1; for(; j>=BIGt; BIGt>>=1) j-=BIGt; j+=BIGt; if(i<j) swap(z[i],z[j]);}
		for(int len=1;len<n;len<<=1) for(int i=0;i<n;i+=len*2) for(int j=0;j<len;j++){
			cpx root=inverse?conj(roots[j+len]):roots[j+len],u=z[i+j],v=z[i+j+len]*root;
			z[i+j]=u+v;z[i+j+len]=u-v;
		}
		if(inverse)for(int i=0; i<n; i++)z[i]/=n;
	}
	vector<int>multiply_BIG(const vector<int>&a,const vector<int>&b,int base) {
		int need=a.size()+b.size(); int n=1; while(n<need) n<<=1; vector<cpx> p(n);
		for(int i=0;i<n;i++) p[i]=cpx(i<(int)a.size()?a[i]:0,i<(int)b.size()?b[i]:0);
		fft(p,false); vector<cpx>ab(n); cpx r(0,-0.25);
		for(int i=0;i<n;i++){int j=(n-i)&(n-1); ab[i]=(p[i]*p[i]-conj(p[j]*p[j]))*r;}
		fft(ab,true); vector<int>result(need); long long carry=0;
		for(int i=0;i<need;i++){long long d=(long long)(ab[i].real()+0.5)+carry; carry=d/base;result[i]=d%base;}
		return result;
	}
	vector<int>multiply_mod(const vector<int>&a,const vector<int>&b,int m) {
		int need=a.size()+b.size()-1; int n=1; while(n<need)n<<=1; vector<cpx>A(n);
		for(size_t i=0;i<a.size();i++){int x=(a[i]%m+m)%m; A[i]=cpx(x&((1<<15)-1),x>>15);}
		fft(A,false); vector<cpx>B(n);
		for(size_t i=0;i<b.size();i++){int x=(b[i]%m+m)%m; B[i]=cpx(x&((1<<15)-1),x>>15);}
		fft(B,false); vector<cpx>fa(n); vector<cpx>fb(n);
		for(int i=0,j=0;i<n;i++,j=n-i) {
			cpx a1=(A[i]+conj(A[j]))*cpx(0.5,0),a2=(A[i]-conj(A[j]))*cpx(0,-0.5);
			cpx b1=(B[i]+conj(B[j]))*cpx(0.5,0),b2=(B[i]-conj(B[j]))*cpx(0,-0.5);
			fa[i]=a1*b1+a2*b2*cpx(0,1); fb[i]=a1*b2+a2*b1;
		}
		fft(fa,true); fft(fb,true); vector<int>res(need);
		for(int i=0;i<need;i++){
			long long aa=(long long)(fa[i].real()+0.5),bb=(long long)(fb[i].real()+0.5),cc=(long long)(fa[i].imag()+0.5);
			res[i]=(aa%m+(bb%m<<15)+(cc%m<<30))%m;
		}
		return res;
	}
	constexpr int digits(int base)noexcept{return base<=1?0:1+digits(base/10);}
	constexpr int base=1000000000,base_digits=digits(base),fft_base=10000,fft_base_digits=digits(fft_base);
	struct Big {
		vector<int>z; int sign;
		Big(long long v=0){*this=v;} 
		Big &operator=(long long v){
			sign=v<0?-1:1,v*=sign,z.clear(); 
			for(;v>0;v=v/base) z.push_back((int)(v%base)); 
			return *this;
		} 
		Big (const string &s){read(s);} 
		Big &operator+=(const Big &other){
			if(sign==other.sign) for(int i=0,carry=0;i<(int)other.z.size()||carry;++i){
				if(i==(int)z.size()) z.push_back(0);
				z[i]+=carry+(i<(int)other.z.size()?other.z[i]:0),carry=z[i]>=base;if(carry)z[i]-=base;
			}else if(other!=0) {*this-=-other;}return*this;
		} 
		friend Big operator+(Big a,const Big &b){a+=b; return a;} 
		Big &operator-=(const Big &other){
			if(sign==other.sign){
				if((sign==1&&*this>=other)||(sign==-1&&*this<=other)){
					for(int i=0,carry=0;i<(int)other.z.size()||carry;++i){
						z[i]-=carry+(i<(int)other.z.size()?other.z[i]:0),carry=z[i]<0;
						if(carry) z[i]+=base;
					}
					trim();
				} else *this=other-*this,this->sign=-this->sign;
			} else {*this+=-other;}return*this;
		} 
		friend Big operator-(Big a,const Big &b) {a-=b; return a;}
		Big &operator*=(int v){
			if(v<0) sign=-sign,v=-v;
			for (int i=0,carry=0;i<(int)z.size()||carry;++i){
				if(i==(int)z.size()) z.push_back(0);
				long long cur=(long long)z[i]*v+carry;
				carry=(int)(cur/base);z[i]=(int)(cur%base);
			}
			trim(); return*this;
		} 
		Big operator*(int v)const{return Big(*this)*=v;}
		friend pair<Big,Big>divmod(const Big&a1,const Big&b1) {
			int norm=base/(b1.z.back()+1);
			Big a=a1.abs()*norm,b=b1.abs()*norm,q,r; q.z.resize(a.z.size());
			for(int i=(int)a.z.size()-1;i>=0;i--) {
				r*=base,r+=a.z[i];
				int s1=b.z.size()<r.z.size()?r.z[b.z.size()]:0,s2=b.z.size()-1<r.z.size()?r.z[b.z.size()-1]:0;
				int d=(int)(((long long)s1*base+s2)/b.z.back());
				r-=b*d;while(r<0)r+=b,--d;q.z[i]=d;
			}
			q.sign=a1.sign*b1.sign,r.sign=a1.sign;
			q.trim(),r.trim(); return {q,r/norm};
		} 
		friend Big sqrt(const Big&a1){
			Big a=a1;
			while(a.z.empty()||a.z.size()%2==1) a.z.push_back(0);
			int n=a.z.size(),firstDigit=(int)::sqrt((double)a.z[n-1]*base+a.z[n-2]),norm=base/(firstDigit+1);
			a*=norm,a*=norm; while(a.z.empty()||a.z.size()%2==1) a.z.push_back(0);
			Big r=(long long)a.z[n-1]*base+a.z[n-2],res;
			firstDigit=(int)::sqrt((double)a.z[n-1]*base+a.z[n-2]); int q=firstDigit;
			for(int j=n/2-1;j>=0;j--){
				for(;;--q){
					Big r1=(r-(res*2*base+q)*q)*base*base+(j>0?(long long)a.z[2*j-1]*base+a.z[2*j-2]:0);
					if(r1>=0){r=r1; break;}
				}
				res*=base;res+=q;
				if(j>0){
					int d1=res.z.size()+2<r.z.size()?r.z[res.z.size()+2]:0;
					int d2=res.z.size()+1<r.z.size()?r.z[res.z.size()+1]:0;
					int d3=res.z.size()<r.z.size()?r.z[res.z.size()]:0;
					q=(int)(((long long)d1*base*base+(long long)d2*base+d3)/(firstDigit*2));
				}
			}
			res.trim(); return res/norm;
		} 
		Big operator/(const Big&v)const{return divmod(*this,v).first;} 
		Big operator%(const Big&v)const{return divmod(*this,v).second;} 
		Big &operator/=(int v){
			if(v<0) sign=-sign,v=-v;
			for(int i=(int)z.size()-1,rem=0;i>=0;--i){
				long long cur=z[i]+rem*(long long)base;
				z[i]=(int)(cur/v),rem=(int)(cur%v);
			}
			trim();return*this;
		} 
		Big operator/(int v)const{return Big(*this)/=v;}
		int operator%(int v) const {
			if(v<0) v=-v; int m=0; for(int i=(int)z.size()-1;i>=0;--i) m=(int)((z[i]+m*(long long)base)%v);
			return m*sign;
		}
		Big&operator*=(const Big &v){*this=*this*v; return*this;} 
		Big&operator/=(const Big &v){*this=*this/v; return*this;} 
		Big&operator%=(const Big &v){*this=*this%v; return*this;}
		friend bool operator<(const Big &u,const Big &v){
			if(u.sign!=v.sign) return u.sign<v.sign; if(u.z.size()!=v.z.size()) return u.z.size()*u.sign<v.z.size()*v.sign;
			for(int i=(int)u.z.size()-1;i>=0;i--) if(u.z[i]!=v.z[i]) return u.z[i]*u.sign<v.z[i]*v.sign;
			return false;
		}
		friend bool operator>(const Big &u,const Big &v){return v<u;} 
		friend bool operator<=(const Big &u,const Big &v){return !(v<u);} 
		friend bool operator>=(const Big &u,const Big &v){return !(u<v);} 
		friend bool operator==(const Big &u,const Big &v){return u.sign==v.sign&&u.z==v.z;} 
		friend bool operator!=(const Big &u,const Big &v){return !(u==v);}
		void trim(){while(!z.empty()&&z.back()==0) z.pop_back(); if(z.empty()) sign=1;}
		bool isZero()const{return z.empty();} 
		friend Big operator-(Big v){if(!v.z.empty()) v.sign=-v.sign; return v;} 
		Big abs()const{return sign==1?*this:-*this;} 
		long long to_num()const{
			long long res=0;
			for(int i=(int)z.size()-1;i>=0;i--) res=res*base+z[i];
			return res*sign;
		} 
		friend Big __gcd(const Big &a,const Big &b){return b.isZero()?a:__gcd(b,a%b);} 
		friend Big abs(const Big &a){return a.abs();}
		void read(const string &s){
			sign=1,z.clear(); int pos=0;
			while(pos<(int)s.size()&&(s[pos]=='-'||s[pos]=='+')){if(s[pos]=='-') sign=-sign; ++pos;}
			for(int i=(int)s.size()-1;i>=pos;i-=base_digits){
				int x=0; for(int j=max(pos,i-base_digits+1);j<=i;j++) x=x*10+s[j]-'0';
				z.push_back(x);
			}
			trim();
		} 
		friend istream&operator>>(istream &stream,Big &v){string s; stream>>s; v.read(s); return stream;} 
		friend ostream&operator<<(ostream &stream,const Big &v){
			if(v.sign==-1) stream<<'-'; stream<<(v.z.empty()?0:v.z.back());
			for(int i=(int)v.z.size()-2; i>=0; --i) stream<<setw(base_digits)<<setfill('0')<<v.z[i];
			return stream;
		}
		static vector<int>convert_base(const vector<int>&a,int old_digits,int new_digits){
			vector<long long> p(max(old_digits,new_digits)+1);
			p[0]=1; for(int i=1;i<(int)p.size();i++) p[i]=p[i-1]*10;
			vector<int> res; long long cur=0; int cur_digits=0;
			for(int v:a) {
				cur+=v*p[cur_digits],cur_digits+=old_digits;
				while(cur_digits>=new_digits)
					res.push_back(int(cur%p[new_digits])),cur/=p[new_digits],cur_digits -= new_digits;
			}
			res.push_back((int)cur); while(!res.empty()&&res.back()==0) res.pop_back();
			return res;
		} 
		Big operator*(const Big&v)const{
			if(min(z.size(),v.z.size())<150) return mul_simple(v);
			Big res;res.sign=sign*v.sign;
			res.z=multiply_BIG(convert_base(z,base_digits,fft_base_digits),
				convert_base(v.z,base_digits,fft_base_digits),fft_base);
			res.z=convert_base(res.z,fft_base_digits,base_digits);
			res.trim(); return res;
		} 
		Big mul_simple(const Big&v)const{Big res;res.sign=sign*v.sign;res.z.resize(z.size()+v.z.size());
			for(int i=0;i<(int)z.size();++i) if(z[i]) for(int j=0,carry=0;j<(int)v.z.size()||carry;++j){
				long long cur=res.z[i+j]+(long long)z[i]*(j<(int)v.z.size()?v.z[j]:0)+carry;
				carry=(int)(cur/base),res.z[i+j]=(int)(cur%base);
			}
			res.trim(); return res;
		}
	};
	mt19937 rng(std::chrono::system_clock::now().time_since_epoch().count());
	Big BIG_rnd(int n){string s; for(int i=0;i<n;i++){s+=uniform_int_distribution<int>('0','9')(rng);} return Big(s);}
} using BIG_num::Big;

可以像其他变量一样用 cincout

cin>>a>>b;

定义一个 \(a\)BIG a;

可以连续定义:

BIG a=2,b,c=3;

加减乘除和一般变量一样,支持 += 一类的,支持比较大小,不支持 BIG 转 int 等,但反过来支持。

分数

template<class Int> class Frac{
public:
    Int top,btm;
    Frac(){top=0;btm=1;} Frac(Int x){top=x;btm=1;} Frac(Int x,Int y){assert(y!=0); top=x,btm=y; this->normalize();}
    double to_num(){return (double)top/btm;}
    friend inline Frac abs(const Frac& x){return Frac(ibs(x.top),x.btm);}
    friend inline Frac Rec(const Frac& x){return Frac(x.btm,x.top);}
    friend inline Frac operator-(const Frac& x){return Frac(-x.top,x.btm);}
    Frac& operator++(){top+=btm; return *this;}
    Frac& operator--(){top-=btm; return *this;}
    Frac operator++(int){Frac x(top); top+=btm; return x;}
    Frac operator--(int){Frac x(top); top-=btm; return x;}
    Frac& operator+=(const Frac& x){
        Int g=Gcd(btm,x.btm);
        top=btm/g*x.top+x.btm/g*top,btm*=x.btm/g; this->normalize();
        return *this;
    }
    Frac& operator-=(const Frac& x){return *this+=(-x);}
    Frac& operator*=(const Frac& x){
        Int g1=Gcd(ibs(top),x.btm),g2=Gcd(ibs(x.top),btm);
        (top/=g1)*=x.top/g2;(btm/=g2)*=x.btm/g1; 
        return *this;
    }
    Frac& operator/=(const Frac& x){return *this*=Rec(x);}
    Frac friend operator+(Frac x,const Frac& y){return x+=y;}
    Frac friend operator-(Frac x,const Frac& y){return x-=y;}
    Frac friend operator*(Frac x,const Frac& y){return x*=y;}
    Frac friend operator/(Frac x,const Frac& y){return x/=y;}
    #define logical_operator(op) bool operator op(const Frac<Int>& y){return (*this-y).top op 0;}
    logical_operator(<) logical_operator(>) logical_operator(<=) logical_operator(>=) logical_operator(==)
    #undef logical_operator
    #define logical_operator(op) template<class U> bool operator op(U y){return (*this-Frac(y)).top op 0;}
    logical_operator(<) logical_operator(>) logical_operator(<=) logical_operator(>=) logical_operator(==)
    #undef logical_operator
    #define logical_operator(op) template<class U> friend bool operator op(U x,const Frac& y){return (Frac(x)-y).top op 0;}
    logical_operator(<) logical_operator(>) logical_operator(<=) logical_operator(>=) logical_operator(==)
    #undef logical_operator	
	friend istream&operator>>(istream &stream,Frac &v){stream>>v.top>>v.btm; v.normalize(); return stream;}
	friend ostream&operator<<(ostream &stream,const Frac &v){stream<<v.top<<'/'<<v.btm; return stream;}//在此更改输出格式
private:
    inline Int Gcd(Int a,Int b){while(b) swap((a%=b),b); return a;}
    Int ibs(const Int& a){return a<0?-a:a;}
    inline void normalize(){Int g=Gcd(ibs(top),btm); top/=g,btm/=g;}
};

定义时要加分子分母类型,类型支持上面的高精。

如果一次性赋值分子分母,用括号括起来。

Frac<int> a(1,3),b=(2,4)

取模数

template<class T> class Modular{
public:
    using Type = typename decay<decltype(T::val)>::type;
    constexpr static Type mod(){return T::val;}
    constexpr Modular():val(){};
    template<class U> Modular(const U& x){val=normalize(x);}
    template<class U> static Type normalize(const U& x) {
        Type v=static_cast<Type>((-mod()<=x&&x<mod())?x:x%mod());
        return (v<0)?v+mod():v;
    }
    const Type& operator()()const{return val;}
    template<class U> explicit operator U()const{return static_cast<U>(val);}
    Modular& operator+=(const Modular& other){if((val+=other.val)>=mod()) val-=mod(); return *this;}
    Modular& operator-=(const Modular& other){if((val-=other.val)<0) val+=mod(); return *this;}
    template<class U> Modular& operator+=(const U& other){return *this+=Modular(other);}
    template<class U> Modular& operator-=(const U& other){return *this-=Modular(other);}
    Modular& operator++(){if(!((++val)^mod())) val=0; return *this;}
    Modular& operator--(){if(!((--val)^(-1))) val=mod()-1; return *this;}
    Modular operator++(int){Modular result(*this); if(!((++val)^mod())) val=0; return result;}
    Modular operator--(int){Modular result(*this); if(!((--val)^(-1))) val=mod()-1; return result;}
    Modular operator-()const{return Modular(-val);}
    template<class U=T>
    typename enable_if<is_same<typename Modular<U>::Type,int>::value,Modular>::type& operator*=(const Modular& rhs){
        val=normalize(static_cast<long long>(val)*static_cast<long long>(rhs.val));
        return *this;
    }
    template<class U=T>
    typename enable_if<is_same<typename Modular<U>::Type,long long>::value,Modular>::type& operator*=(const Modular& rhs) {
        long long q=static_cast<long long>(static_cast<long double>(val)*rhs.val/mod());
        val=normalize(val*rhs.val-q*mod()); return *this;
    }
    template<class U=T>
    typename enable_if<!is_integral<typename Modular<U>::Type>::value,Modular>::type& operator*=(const Modular& rhs) {
        val=normalize(val*rhs.val);
        return *this;
    }
    Modular& operator/=(const Modular& other){return *this*=Modular(Inv(other.val,mod()));}
    friend const Type& abs(const Modular& x){return x.val;}
    template<class V> friend bool operator==(const Modular<V>& lhs,const Modular<V>& rhs){return lhs.val==rhs.val;}
    template<class V,class U> friend bool operator==(const Modular<V>& lhs,U rhs){return lhs==Modular<V>(rhs);}
    template<class V,class U> friend bool operator==(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)==rhs;}
    template<class V> friend bool operator!=(const Modular<V>& lhs,const Modular<V>& rhs){return !(lhs==rhs);}
    template<class V,class U> friend bool operator!=(const Modular<V>& lhs,U rhs){return !(lhs==rhs);}
    template<class V,class U> friend bool operator!=(U lhs,const Modular<V>& rhs){return !(lhs==rhs);}
    template<class V> friend bool operator<(const Modular<V>& lhs,const Modular<V>& rhs){return lhs.val<rhs.val;}
    template<class V,class U> friend bool operator<(const Modular<V>& lhs,U rhs){return lhs<Modular<V>(rhs);}
    template<class V,class U> friend bool operator<(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)<rhs;}
    template<class V> friend bool operator<=(const Modular<V>& lhs,const Modular<V>& rhs){return lhs.val<=rhs.val;}
    template<class V,class U> friend bool operator<=(const Modular<V>& lhs,U rhs){return lhs<=Modular<V>(rhs);}
    template<class V,class U> friend bool operator<=(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)<=rhs;}
    template<class V> friend bool operator>(const Modular<V>& lhs,const Modular<V>& rhs){return lhs.val>rhs.val;}
    template<class V,class U> friend bool operator>(const Modular<V>& lhs,U rhs){return lhs>Modular<V>(rhs);}
    template<class V,class U> friend bool operator>(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)>rhs;}
    template<class V> friend bool operator>=(const Modular<V>& lhs,const Modular<V>& rhs){return lhs.val>=rhs.val;}
    template<class V,class U> friend bool operator>=(const Modular<V>& lhs,U rhs){return lhs>=Modular<V>(rhs);}
    template<class V,class U> friend bool operator>=(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)>=rhs;}
    template<class V> friend Modular<V> operator+(const Modular<V>& lhs,const Modular<V>& rhs){return Modular<V>(lhs)+=rhs;}
    template<class V,class U> friend Modular<V> operator+(const Modular<V>& lhs,U rhs){return Modular<V>(lhs)+=rhs;}
    template<class V,class U> friend Modular<V> operator+(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)+=rhs;}
    template<class V> friend Modular<V> operator-(const Modular<V>& lhs,const Modular<V>& rhs){return Modular<V>(lhs)-=rhs;}
    template<class V,class U> friend Modular<V> operator-(const Modular<V>& lhs,U rhs){return Modular<V>(lhs)-=rhs;}
    template<class V,class U> friend Modular<V> operator-(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)-=rhs;}
    template<class V> friend Modular<V> operator*(const Modular<V>& lhs,const Modular<V>& rhs){return Modular<V>(lhs)*=rhs;}
    template<class V,class U> friend Modular<V> operator*(const Modular<V>& lhs,U rhs){return Modular<V>(lhs)*=rhs;}
    template<class V,class U> friend Modular<V> operator*(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)*=rhs;}
    template<class V> friend Modular<V> operator/(const Modular<V>& lhs,const Modular<V>& rhs){return Modular<V>(lhs)/=rhs;}
    template<class V,class U> friend Modular<V> operator/(const Modular<V>& lhs,U rhs){return Modular<V>(lhs)/=rhs;}
    template<class V,class U> friend Modular<V> operator/(U lhs,const Modular<V>& rhs){return Modular<V>(lhs)/=rhs;}
    template<class V> friend string to_string(const Modular<V>& number){return to_string(number());}
	template<class V> friend istream&operator>>(istream &stream,Modular<V>& v){
		stream>>v.val; v.val=normalize(v.val); return stream;
	}
	template<class V> friend ostream&operator<<(ostream &stream,const Modular<V>& v){stream<<v(); return stream;}
private:
    Type val;
    template<class V> V Inv(const V& x,const V& m) {
        assert(x!=0); V u=0,v=1,a=x,b=m,t;
        while(a!=0) t=b/a,swap(a,b-=t*a),swap(u-=t*v,v);
        assert(b==1); return u;
    }
};

定义类似:

struct VarMod{static const int val=998244353;};
using Mint=Modular<VarMod>; // 固定模数
Mint a;
struct VarMod{static int val;};
int VarMod::val; int& MOD = VarMod::val;
using Mint=Modular<VarMod>; // 不固定模数,通过修改 MOD 改变模数
Mint a;
posted @ 2024-03-03 20:24  xrlong  阅读(9)  评论(0编辑  收藏  举报