Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <vector>
- #include <cstdlib>
- #include <cctype>
- #include <cstring>
- #include <sstream>
- #include <iostream>
- #include <cstdio>
- #include <cmath>
- #include <climits>
- using namespace std;
- typedef long long ll;
- typedef long double ld;
- typedef unsigned long long ull;
- typedef unsigned int uint;
- #ifdef _MSC_VER
- const ld M_PI=(ld)3.1415926535897932384626433832795;
- #endif
- namespace Numbers
- {
- void clear(vector <int>&); //for GNU C++
- class Lint
- {
- private:
- static const int base=1e6;
- static const int LOG_BASE=6;
- static const int BIG_NUM_SZ=1e6;
- static const Lint ONE;
- vector <int> v;
- bool sgn;
- public:
- Lint()
- {
- sgn=false;
- }
- Lint(int a)
- {
- char s[12];
- sprintf(s,"%d",a);
- init(s);
- }
- Lint(unsigned int a)
- {
- char s[12];
- sprintf(s,"%u",a);
- init(s);
- }
- Lint(ll a)
- {
- string s;
- stringstream tmp;
- tmp<<a;
- tmp>>s;
- init(s);
- }
- Lint(ull a)
- {
- string s;
- stringstream tmp;
- tmp<<a;
- tmp>>s;
- init(s);
- }
- Lint(const char* s)
- {
- init(s);
- }
- Lint(const string& s)
- {
- init(s);
- }
- void swap(Lint &b)
- {
- std::swap(sgn,b.sgn);
- v.swap(b.v);
- }
- /*operator bool()
- {
- return !is_null();
- }*/
- Lint operator -()
- {
- sgn^=true;
- if (is_null())
- sgn=false;
- return *this;
- }
- Lint& operator +=(Lint b)
- {
- if (!(sgn^b.sgn))
- this->add(b);
- else
- {
- int res=this->cmp(b);
- if (sgn && !b.sgn)
- {
- if (res<=0)
- {
- this->swap(b);
- this->sub(b);
- sgn=false;
- } else
- this->sub(b);
- } else
- {
- if (res>=0)
- this->sub(b);
- else
- {
- this->swap(b);
- this->sub(b);
- sgn=true;
- }
- }
- }
- return *this;
- }
- Lint& operator -=(Lint b)
- {
- int res=this->cmp(b);
- if (!sgn && !b.sgn)
- {
- if (res>=0)
- this->sub(b);
- else
- {
- this->swap(b);
- this->sub(b);
- sgn=true;
- }
- } else if (sgn && b.sgn)
- {
- if (res<=0)
- {
- this->swap(b);
- this->sub(b);
- sgn=false;
- } else
- this->sub(b);
- } else if (sgn || b.sgn)
- this->add(b);
- return *this;
- }
- Lint& operator *=(const Lint& b)
- {
- if (len()*1ll*b.len()>=BIG_NUM_SZ)
- this->fast_mul(b);
- else
- this->mul(b);
- sgn^=b.sgn;
- if (is_null())
- sgn=false;
- return *this;
- }
- Lint& operator /=(const Lint& b)
- {
- bool res=(sgn^b.sgn);
- Lint c,d;
- this->div_mod(b,c,d);
- this->swap(c);
- sgn=res;
- if (is_null())
- sgn=false;
- return *this;
- }
- Lint& operator %=(const Lint& b)
- {
- Lint c,d;
- this->div_mod(b,c,d);
- this->swap(d);
- if (sgn)
- *this+=b;
- sgn=false;
- return *this;
- }
- Lint& operator +=(ll b)
- {
- return *this+=Lint(b);
- }
- Lint& operator -=(ll b)
- {
- return *this-=Lint(b);
- }
- Lint& operator *=(ll b)
- {
- return *this*=Lint(b);
- }
- Lint& operator /=(ll b)
- {
- ll tmp=(1ll<<63);
- if (b!=tmp && b<base && -b<base)
- {
- uint r;
- this->short_div_mod((uint)(b<0?-b:b),r);
- sgn^=(b<0);
- if (is_null())
- sgn=false;
- return *this;
- } else
- return *this/=Lint(b);
- }
- Lint& operator %=(ll b)
- {
- ll tmp=(1ll<<63);
- if (b!=tmp && b<base && -b<base)
- {
- uint r;
- this->short_div_mod((uint)(b<0?-b:b),r);
- clear(v);
- if (sgn)
- v.push_back(r+b);
- else
- v.push_back(r);
- sgn=false;
- return *this;
- } else
- return *this%=Lint(b);
- }
- Lint& operator ++()
- {
- return *this+=ONE;
- }
- Lint operator ++(int)
- {
- Lint a=*this;
- *this+=ONE;
- return a;
- }
- Lint& operator --()
- {
- return *this-=ONE;
- }
- Lint operator --(int)
- {
- Lint a=*this;
- *this-=ONE;
- return a;
- }
- friend Lint operator +(const Lint&,const Lint&);
- friend Lint operator -(const Lint&,const Lint&);
- friend Lint operator *(const Lint&,const Lint&);
- friend Lint operator /(const Lint&,const Lint&);
- friend Lint operator %(const Lint&,const Lint&);
- friend Lint operator /(const Lint&,ll);
- friend Lint operator %(const Lint&,ll);
- friend bool operator <(const Lint&,const Lint&);
- friend bool operator ==(const Lint&,const Lint&);
- friend bool operator >(const Lint&,const Lint&);
- friend bool operator !=(const Lint&,const Lint&);
- friend bool operator <=(const Lint&,const Lint&);
- friend bool operator >=(const Lint&,const Lint&);
- friend istream& operator >>(istream&,Lint&);
- friend ostream& operator <<(ostream&,const Lint&);
- string std_str() const
- {
- string ans;
- char buf[10],form[10];
- sprintf(form,"%%0%dd",LOG_BASE);
- if (sgn)
- ans+='-';
- sprintf(buf,"%d",v.empty()?0:v.back());
- ans+=buf;
- for(int i=(int)len()-2;i>=0;i--)
- {
- sprintf(buf,form,v[i]);
- ans+=buf;
- }
- return ans;
- }
- const char* c_str() const
- {
- return this->std_str().c_str();
- }
- private:
- class Complex
- {
- private:
- ld r,i;
- public:
- Complex()
- {
- r=i=0.0;
- }
- Complex(ld x,ld y=0): r(x),i(y) {}
- Complex& operator =(int a)
- {
- r=a;
- i=0;
- return *this;
- }
- ld imag() const
- {
- return i;
- }
- ld real() const
- {
- return r;
- }
- Complex& operator +=(Complex& b)
- {
- r+=b.r;
- i+=b.i;
- return *this;
- }
- Complex& operator -=(Complex& b)
- {
- r-=b.r;
- i-=b.i;
- return *this;
- }
- Complex& operator *=(Complex& b)
- {
- ld t=r;
- r=r*b.r-i*b.i;
- i=t*b.i+b.r*i;
- return *this;
- }
- Complex& operator /=(ld b)
- {
- r/=b;
- i/=b;
- return *this;
- }
- Complex operator -(Complex b)
- {
- Complex c=*this;
- return c-=b;
- }
- Complex operator +(Complex b)
- {
- Complex c=*this;
- return c+=b;
- }
- Complex operator *(Complex b)
- {
- Complex c=*this;
- return c*=b;
- }
- };
- friend void fft(vector <Complex>&,bool);
- uint len() const
- {
- return v.size();
- }
- int cmp(const Lint& b) const
- {
- if (is_null() && b.is_null())
- return 0;
- if (len()<b.len())
- return -1;
- else if (len()>b.len())
- return 1;
- for(int i=(int)len()-1;i>=0;i--)
- if (v[i]<b.v[i])
- return -1;
- else if (v[i]>b.v[i])
- return 1;
- return 0;
- }
- void init(const string& s)
- {
- int st=0;
- if (s[0]=='-')
- {
- sgn=true;
- st=1;
- } else
- sgn=false;
- clear(v);
- for(int i=s.size();i>st;i-=LOG_BASE)
- {
- int cur,l,r;
- if (i-st>=LOG_BASE)
- {
- l=i-LOG_BASE;
- r=LOG_BASE;
- } else
- {
- l=st;
- r=i-st;
- }
- cur=atoi(s.substr(l,r).c_str());
- if (!cur)
- {
- bool ok=true;
- for(int j=l;j<l+r && ok;j++)
- if (!isdigit(s[j]))
- ok=false;
- if (!ok) ; //error: not a number
- }
- v.push_back(cur);
- }
- if (is_null())
- sgn=false;
- }
- bool is_null() const
- {
- return v.empty() || v.size()==1 && v.back()==0;
- }
- void add(const Lint& b)
- {
- int r=0;
- for(int i=0;i<max(len(),b.len()) || r;i++)
- {
- if (i==len())
- v.push_back(0);
- v[i]+=r+(i<b.len()?b.v[i]:0);
- r=v[i]>=base;
- if (r)
- v[i]-=base;
- }
- }
- void sub(const Lint& b)
- {
- int r=0;
- for(int i=0;i<b.len() || r;i++)
- {
- v[i]-=(r+(i<b.len()?b.v[i]:0));
- r=v[i]<0;
- if (r)
- v[i]+=base;
- }
- while (len()>1 && v.back()==0)
- v.pop_back();
- }
- void mul(const Lint& b)
- {
- vector <int> c(len()+b.len());
- for(int i=0;i<len();i++)
- for(int j=0,r=0;j<b.len() || r;j++)
- {
- ll cur=c[i+j]+v[i]*1ll*(j<b.len()?b.v[j]:0)+r;
- c[i+j]=cur%base;
- r=cur/base;
- }
- while (c.size()>1 && c.back()==0)
- c.pop_back();
- v=c;
- }
- void fast_mul(const Lint& b)
- {
- int n=1;
- while (n<max(len(),b.len()))
- n<<=1;
- n<<=1;
- vector <Complex> a1(n),a2(n);
- copy(v.begin(),v.end(),a1.begin());
- copy(b.v.begin(),b.v.end(),a2.begin());
- if (!len())
- a1.push_back(0);
- if (!b.len())
- a2.push_back(0);
- fft(a1,false);
- fft(a2,false);
- for(int i=0;i<n;i++)
- a1[i]*=a2[i];
- fft(a1,true);
- v.resize(n);
- for(int i=0,r=0;i<n;i++)
- {
- ll cur=(ll)(a1[i].real()+0.5)+r;
- v[i]=cur%base;
- r=cur/base;
- }
- while (len()>1 && v.back()==0)
- v.pop_back();
- }
- void div_mod(const Lint& b,Lint& c,Lint& cur)
- {
- c.v.resize(len());
- for(int i=(int)len()-1;i>=0;i--)
- {
- cur.v.insert(cur.v.begin(),v[i]);
- while (cur.len()>1 && cur.v.back()==0)
- cur.v.pop_back();
- int l=0,r=base;
- while (l<r-1)
- {
- int m=(l+r)>>1;
- Lint tmp=b;
- tmp.mul(Lint(m));
- if (tmp.cmp(cur)<=0)
- l=m;
- else
- r=m;
- }
- c.v[i]=l;
- Lint tmp=b;
- tmp*=l;
- cur-=tmp;
- }
- while (c.len()>1 && c.v.back()==0)
- c.v.pop_back();
- }
- void short_div_mod(uint b,uint& cur)
- {
- cur=0;
- for(int i=(int)len()-1;i>=0;i--)
- {
- ll tmp=v[i]+cur*1ll*base;
- v[i]=tmp/b;
- cur=tmp%b;
- }
- while (len()>1 && v.back()==0)
- v.pop_back();
- }
- };
- const Lint Lint::ONE=1;
- void clear(vector <int>& a)
- {
- vector <int> tmp;
- a.swap(tmp);
- }
- void fft(vector <Lint::Complex>& a,bool inv)
- {
- int n=a.size();
- if (n==1)
- return;
- ld ang=2*M_PI/n*(inv?-1:1);
- Lint::Complex wn=Lint::Complex(cos(ang),sin(ang)),w=1;
- vector <Lint::Complex> a0(n/2),a1(n/2);
- for(int i=0,j=0;i<n;i+=2,j++)
- {
- a0[j]=a[i];
- a1[j]=a[i+1];
- }
- fft(a0,inv);
- fft(a1,inv);
- for(int i=0;i<n/2;i++)
- {
- a[i]=a0[i]+w*a1[i];
- a[i+n/2]=a0[i]-w*a1[i];
- w*=wn;
- if (inv)
- {
- a[i]/=2;
- a[i+n/2]/=2;
- }
- }
- }
- Lint operator +(const Lint& a,const Lint& b)
- {
- Lint tmp=a;
- return tmp+=b;
- }
- Lint operator -(const Lint& a,const Lint& b)
- {
- Lint tmp=a;
- return tmp-=b;
- }
- Lint operator *(const Lint& a,const Lint& b)
- {
- Lint tmp=a;
- return tmp*=b;
- }
- Lint operator /(const Lint& a,const Lint& b)
- {
- Lint tmp=a;
- return tmp/=b;
- }
- Lint operator %(const Lint& a,const Lint& b)
- {
- Lint tmp=a;
- return tmp%=b;
- }
- Lint operator /(const Lint& a,ll b)
- {
- Lint tmp=a;
- return tmp/=b;
- }
- Lint operator %(const Lint& a,ll b)
- {
- Lint tmp=a;
- return tmp%=b;
- }
- bool operator <(const Lint& a,const Lint& b)
- {
- bool cod=false;
- if (a.is_null() && b.is_null())
- return false;
- if (a.sgn && !b.sgn)
- return true;
- else if (!a.sgn && b.sgn)
- return false;
- else if (a.sgn && b.sgn)
- cod=true;
- if (a.len()<b.len())
- return cod^1;
- else if (a.len()>b.len())
- return cod;
- for(int i=(int)a.len()-1;i>=0;i--)
- if (a.v[i]<b.v[i])
- return cod^1;
- else if (a.v[i]>b.v[i])
- return cod;
- return false;
- }
- bool operator ==(const Lint& a,const Lint& b)
- {
- if (a.is_null() && b.is_null())
- return true;
- if (a.sgn!=b.sgn || a.len()!=b.len())
- return false;
- for(int i=0;i<a.len();i++)
- if (a.v[i]!=b.v[i])
- return false;
- return true;
- }
- bool operator <=(const Lint& a,const Lint& b)
- {
- return a<b || a==b;
- }
- bool operator >(const Lint& a,const Lint& b)
- {
- return !(a<=b);
- }
- bool operator >=(const Lint& a,const Lint& b)
- {
- return !(a<b);
- }
- bool operator !=(const Lint& a,const Lint& b)
- {
- return !(a==b);
- }
- istream& operator >>(istream& in,Lint& a)
- {
- string s;
- in>>s;
- a.init(s);
- return in;
- }
- ostream& operator <<(ostream& out,const Lint& a)
- {
- string s=a.std_str();
- out<<s;
- return out;
- }
- };
- typedef Numbers::Lint Lint;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement