【转载】高精度类

时间:2021-09-06 20:33:05
//
//Search
//
//happyZYM 的博客
//题解 UVA10213 【How Many Pieces of Land ?】
//
//2018-05-16 20:09:51thumb_up 0
//紫书上的思路很容易理解,但时间复杂度太高。在网上搜了半天终于在*上搜到了O(1)算法。 以下证明过程摘自*: pic
//
//即答案为 (n*n*n*n-6*n*n*n+23*n*n-18*n+24)/24
//
//由于 0≤n≤2^31,需要高精度。
//
//c++代码如下:
#include<iostream>
#ifndef BIGINT
#define BIGINT
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
template<class T_queue>
struct Node_queue_for_bigint
{
    T_queue num;
    Node_queue_for_bigint *next;
    Node_queue_for_bigint()
    {
        next=0;
    }
};
template<class a_queue>
struct queue_for_bigint
{
    Node_queue_for_bigint<a_queue> *head,*tail,*L;
    bool isn;
    int SIZE_queue;
    void beginning()
    {
        head=tail=L=0;
        isn=0;
        head=tail=new Node_queue_for_bigint<a_queue>;
        tail->next=head;
        SIZE_queue=0;
        isn=1;
    }
    queue_for_bigint()
    {
        beginning();
    }
    ~queue_for_bigint()
    {
        Node_queue_for_bigint<a_queue> *p=head,*tp;
        p=p->next;
        while(p!=head)
        {
            tp=p->next;
            delete p;
            p=tp;
        }
    }
    bool push(a_queue s)
    {
        SIZE_queue++;
        tail->num=s;
        if(tail->next==head)
        {
            tail->next=new Node_queue_for_bigint<a_queue>;
            tail->next->next=head;
            L=tail;
            tail=tail->next;
            return 1;
        }
        L=tail;
        tail=tail->next;
        return 0;
    }
    bool pop()
    {
        if(head==tail) return 1;
        head=head->next;
        SIZE_queue--;
        return 0;
    } 
    a_queue& front()
    {
        return head->num;
    } 
    a_queue& back()
    {
        return L->num;
    }
    int size()
    {
        return SIZE_queue;
    }
    void clear()
    {
        SIZE_queue=0;
        tail=head;
    }
    bool operator=(queue_for_bigint<a_queue>b)
    {
        if(!isn)
        {
            this->beginning();
            isn=1;
        }
        this->clear();
        Node_queue_for_bigint<a_queue> *p=b.head;
        while(p!=b.tail)
        {
            this->push(p->num);
            p=p->next;
        }
        return 0;
    }
};
int CacheSize=25;//try to use the cache
queue_for_bigint<char*> Mems;
queue_for_bigint<int> q;
queue_for_bigint<char> cache;
struct BigInt
{
    char f:4,nAn:4;
    std::vector<int> num;
    static const int base=100000000;
    BigInt()
    {
        f=0;
        nAn=0;
        num.push_back(0);
    }
    template<class TYPE>
    BigInt(TYPE V)
    {
        f=nAn=0;
        *this=V;
    }
    void format()
    {
        while(num.size()>1&&num[num.size()-1]<=0) num.erase(num.end()-1);
        if(num.size()==1&&num[0]==0) f=0;
        if(num.size()==0) num.push_back(0),f=nAn=0;
    }
    //Input and Output
    char* c_str()
    {
        char *p,*ptr;
        if(!nAn)
        {
            p=new char[num.size()*8+16];
            ptr=p;
            memset(p,0,num.size()*8+16);
            if(f) sprintf(p,"-"),p++;
            sprintf(p,"%d",num[num.size()-1]);
            for(int i=num.size()-2;i>=0;i--)
            {
                while(*p) p++;
                sprintf(p,"%08d",num[i]);
            }
        }
        else
        {
            p=new char[5];
            sprintf(p,"nan");
        }
        Mems.push(ptr);
        return ptr;
    }
    std::string str()
    {
        std::string ss=c_str();
        return ss;
    }
    BigInt operator=(char* s)
    {
        f=0;
        if(s==0) return BigInt();
        if(*s=='-')
        {
            f=1;
            s++;
        }
        int len=strlen(s),add=0,i,t;
        num.resize(len/8+1);
        char *p=s+len-1;
        while(p-7>=s)
        {
            t=0;
            for(i=-7;i<=0;i++)
                if(p+i>=s) t=t*10+*(p+i)-'0';
            p-=8;
            num[add++]=t;
        }
        if(p>=s)
        {
            t=0;
            while(s<=p) t=t*10+*(s++)-'0';
            num[add++]=t;
        }
        while(num.size()>add) num.erase(num.end()-1);
        return *this;
    }
    BigInt operator=(std::string ss)
    {
        char *s=&ss[0];
        f=0;
        if(s==0) return BigInt();
        if(*s=='-')
        {
            f=1;
            s++;
        }
        int len=strlen(s),add=0,i,t;
        num.resize(len/8+1);
        char *p=s+len-1;
        while(p>=s)
        {
            t=0;
            for(i=-7;i<=0;i++)
                if(p+i>=s) t=t*10+*(p+i)-'0';
            p-=8;
            num[add++]=t;
        }
        while(num.size()>add) num.erase(num.end()-1);
        return *this;
    }
    BigInt operator=(int v)
    {
        f=0;
        if(v<0)
        {
            f=1;
            v=-v;
        }
        q.clear();
        if(v==0) q.push(0);
        else
            while(v>0)
            {
                q.push(v%base);
                v/=base;
            }
        num.resize(q.size());
        for(int i=0;q.size()>0;i++)
        {
            num[i]=q.front();
            q.pop();
        }
        return *this;
    }
    BigInt operator=(unsigned int v)
    {
        f=0;
        q.clear();
        if(v==0) q.push(0);
        else
            while(v>0)
            {
                q.push(v%base);
                v/=base;
            }
        num.resize(q.size());
        for(int i=0;q.size()>0;i++)
        {
            num[i]=q.front();
            q.pop();
        }
        return *this;
    }
    BigInt operator=(long long v)
    {
        f=0;
        if(v<0)
        {
            f=1;
            v=-v;
        }
        q.clear();
        if(v==0) q.push(0);
        else
            while(v>0)
            {
                q.push(v%base);
                v/=base;
            }
        num.resize(q.size());
        for(int i=0;q.size()>0;i++)
        {
            num[i]=q.front();
            q.pop();
        }
        return *this;
    }
    BigInt operator=(unsigned long long v)
    {
        f=0;
        q.clear();
        if(v==0) q.push(0);
        else
            while(v>0)
            {
                q.push(v%base);
                v/=base;
            }
        num.resize(q.size());
        for(int i=0;q.size()>0;i++)
        {
            num[i]=q.front();
            q.pop();
        }
        return *this;
    }
    //====================/
    //In-situ operation
    BigInt operator++()
    {
        format();
        if(!f)
        {
            num[0]++;
            int i=1;
            while(i<num.size()&&num[i-1]>=base)
                num[i]++,num[i-1]-=base,i++;
            if(num[i-1]>=base)
                num.push_back(1),num[i-1]-=base;
        }
        else
        {
            num[0]--;
            int i=1;
            while(i<num.size()&&num[i-1]<0)
                num[i]--,num[i-1]+=base,i++;
            format();
        }
        return *this;
    }
    BigInt operator++(int)
    {
        format();
        BigInt t=*this;
        if(!f)
        {
            num[0]++;
            int i=1;
            while(i<num.size()&&num[i-1]>=base)
                num[i]++,num[i-1]-=base,i++;
            if(num[i-1]>=base)
                num.push_back(1),num[i-1]-=base;
        }
        else
        {
            num[0]--;
            int i=1;
            while(i<num.size()&&num[i-1]<0)
                num[i]--,num[i-1]+=base,i++;
            format();
        }
        return t;
    }
    BigInt operator--()
    {
        format();
        if(!f)
        {
            num[0]--;
            int i=1;
            while(i<num.size()&&num[i-1]<0)
                num[i]--,num[i-1]+=base,i++;
            if(num[i-1]<0)
                *this=-1;
            format();
        }
        else
        {
            num[0]++;
            int i=1;
            while(i<num.size()&&num[i-1]>=base)
                num[i]++,num[i-1]-=base,i++;
            if(num[i-1]>=base)
                num.push_back(1),num[i-1]-=base;
        }
        return *this;
    }
    BigInt operator--(int)
    {
        format();
        BigInt t=*this;
        if(!f)
        {
            num[0]--;
            int i=1;
            while(i<num.size()&&num[i-1]<0)
                num[i]--,num[i-1]+=base,i++;
            if(num[i-1]<0)
                *this=-1;
            format();
        }
        else
        {
            num[0]++;
            int i=1;
            while(i<num.size()&&num[i-1]>=base)
                num[i]++,num[i-1]-=base,i++;
            if(num[i-1]>=base)
                num.push_back(1),num[i-1]-=base;
        }
        return t;
    }
    //=====================/
};
//compare operations
bool operator<(BigInt a,BigInt b)
{
    a.format();
    b.format();
    if(a.f!=b.f) return a.f>b.f;
    if(a.f==0)
    {
        if(a.num.size()<b.num.size()) return 1;
        else if(a.num.size()>b.num.size()) return 0;
        for(int i=a.num.size()-1;i>=0;i--)
            if(a.num[i]<b.num[i]) return 1;
            else if(a.num[i]>b.num[i]) return 0;
    }
    else
    {
        if(a.num.size()>b.num.size()) return 1;
        else if(a.num.size()<b.num.size()) return 0;
        for(int i=a.num.size()-1;i>=0;i--)
            if(a.num[i]>b.num[i]) return 1;
            else if(a.num[i]<b.num[i]) return 0;
    }
    return 0;
}
bool operator==(BigInt a,BigInt b)
{
    a.format();
    b.format();
    if(a.f!=b.f) return 0;
    if(a.num.size()!=b.num.size()) return 0;
    for(int i=a.num.size()-1;i>=0;i--)
        if(a.num[i]!=b.num[i]) return 0;
    return 1;
}
bool operator!=(BigInt a,BigInt b)
{
    a.format();
    b.format();
    if(a.f!=b.f) return 1;
    if(a.num.size()!=b.num.size()) return 1;
    for(int i=a.num.size()-1;i>=0;i--)
        if(a.num[i]!=b.num[i]) return 1;
    return 0;
}
bool operator>(BigInt a,BigInt b)
{
    a.format();
    b.format();
    if(a.f!=b.f) return a.f<b.f;
    if(a.f==0)
    {
        if(a.num.size()>b.num.size()) return 1;
        else if(a.num.size()<b.num.size()) return 0;
        for(int i=a.num.size()-1;i>=0;i--)
            if(a.num[i]>b.num[i]) return 1;
            else if(a.num[i]<b.num[i]) return 0;
    }
    else
    {
        if(a.num.size()<b.num.size()) return 1;
        else if(a.num.size()>b.num.size()) return 0;
        for(int i=a.num.size()-1;i>=0;i--)
            if(a.num[i]<b.num[i]) return 1;
            else if(a.num[i]>b.num[i]) return 0;
    }
    return 0;
}
bool operator<=(const BigInt &a,const BigInt &b){return (a<b||a==b);}
bool operator>=(const BigInt &a,const BigInt &b){return (a>b||a==b);}
//=================/
//maths operations
BigInt operator+(BigInt a,BigInt b);
BigInt operator-(BigInt a,BigInt b);
BigInt operator*(BigInt a,BigInt b);
BigInt operator/(BigInt a,BigInt b);
void BigInt_add     (BigInt &a,BigInt &b,BigInt &c);
void BigInt_minus   (BigInt &a,BigInt &b,BigInt &c);
void BigInt_times   (BigInt &a,BigInt &b,BigInt &c);
void BigInt_divide  (BigInt &a,BigInt &b,BigInt &c);
void BigInt_add(BigInt &a,BigInt &b,BigInt &c)
{
    a.format();
    b.format();
    c.nAn=(a.nAn==1||b.nAn==1);
    if(c.nAn) return;
    if(a.f)
    {
        if(b.f)
        {
            a.f=b.f=0;
            BigInt_add(a,b,c);
            a.f=b.f=c.f=1;
            return;
        }
        else
        {
            a.f=0;
            BigInt_minus(b,a,c);
            a.f=1;
            return;
        }
    }
    else if(b.f)
    {
        b.f=0;
        BigInt_minus(a,b,c);
        b.f=1;
        return;
    }
    int t=0,t2=std::max(a.num.size(),b.num.size())+1;
    c.num.resize(t2);
    memset(&c.num[0],0,t2*4);
    for(int i=0;i<t2;i++)
    {
        if(i<a.num.size()) t+=a.num[i];
        if(i<b.num.size()) t+=b.num[i];
        c.num[i]=t%BigInt::base;
        t/=BigInt::base;
    }
    c.format();
}
void BigInt_minus(BigInt &a,BigInt &b,BigInt &c)
{
    a.format();
    b.format();
    c.nAn=(a.nAn==1||b.nAn==1);
    if(c.nAn) return;
    if(a.f)
    {
        if(b.f)
        {
            a.f=b.f=0;
            BigInt_minus(b,a,c);
            a.f=b.f=1;
            return;
        }
        else
        {
            a.f=0;
            BigInt_add(a,b,c);
            a.f=c.f=1;
            return;
        }
    }
    else if(b.f)
    {
        b.f=0;
        BigInt_add(a,b,c);
        b.f=1;
        return;
    }
    if(a<b)
    {
        BigInt_minus(b,a,c);
        c.f=1;
        return;
    }
    c=a;
    int z=0,k;
    for(int i=0;i<b.num.size();i++)
    {
        c.num[i]=c.num[i]-b.num[i];
        if(c.num[i]<0)
        {
            c.num[i]+=BigInt::base;
            z=1;
        }
        else z=0;
        k=i+1;
        while(z&&k<c.num.size())
        {
            c.num[k]--;
            if(c.num[k]<0)
            {
                z=1;
                c.num[k]+BigInt::base;
            }
            else z=0;
            k++;
        }
    }
    c.format();
}
void BigInt_times(BigInt &a,BigInt &b,BigInt &c)
{
    a.format();
    b.format();
    c.nAn=(a.nAn==1||b.nAn==1);
    if(c.nAn) return;
    c.num.resize(a.num.size()+b.num.size());
    memset(&c.num[0],0,(a.num.size()+b.num.size())*4);
    int i,j,k,I,J;
    long long t;
    int *A,*B,*C,As=a.num.size(),Bs=b.num.size();
    A=&(a.num[0]);
    B=&(b.num[0]);
    C=&(c.num[0]);
    for(i=0;i<As;i+=CacheSize)
        for(j=0;j<Bs;j+=CacheSize)
            for(I=i;I<i+CacheSize&&I<As;I++)
                for(J=j;J<j+CacheSize&&J<Bs;J++)
                {
                    t=(long long)A[I]*B[J];
                    t=t+C[I+J];
                    C[I+J]=t%BigInt::base;
                    k=I+J+1;
                    t/=BigInt::base;
                    while(t>0)
                    {
                        t=t+C[k];
                        C[k++]=t%BigInt::base;
                        t=t/BigInt::base;
                    }
                }
    c.f=(a.f!=b.f);
    c.format();
}
void BigInt_divide(BigInt &a,BigInt &b,BigInt &c)
{
    BigInt t;
    a.format();
    b.format();
    bool af=a.f,bf=b.f;
    a.f=b.f=0;
    if(a<b)
    {
        c=BigInt();
        return;
    }
    c.nAn=(a.nAn==1||b.nAn==1||(b.num.size()==1&&b.num[0]==0));
    c.f=0;
    if(c.nAn) return;
    c.num.resize(a.num.size()-b.num.size()+1,0);
    int L,R;
    for(int i=c.num.size()-1;i>=0;i--)
    {
        L=0;
        R=a.base-1;
        while(L+1<R)
        {
            c.num[i]=(L+R)/2;
            BigInt_times(b,c,t);
            if(t>a) R=(L+R)/2;
            else L=(L+R)/2;
        }
        c.num[i]=L;
    }
    c.format();
    a.f=af;
    b.f=bf;
    c.f=(af!=bf);
}
BigInt operator+(BigInt a,BigInt b)
{
    BigInt t;
    BigInt_add(a,b,t);
    return t;
}
BigInt operator+=(BigInt &a,BigInt b)
{
    BigInt t;
    BigInt_add(a,b,t);
    return a=t;
}
BigInt operator-(BigInt a,BigInt b)
{
    BigInt t;
    BigInt_minus(a,b,t);
    return t;
}
BigInt operator-=(BigInt &a,BigInt b)
{
    BigInt t;
    BigInt_minus(a,b,t);
    return a=t;
}
BigInt operator*(BigInt a,BigInt b)
{
    BigInt t;
    BigInt_times(a,b,t);
    return t;
}
BigInt operator*=(BigInt &a,BigInt b)
{
    BigInt t;
    BigInt_times(a,b,t);
    return a=t;
}
BigInt operator/(BigInt a,BigInt b)
{
    BigInt c;
    BigInt_divide(a,b,c);
    return c;
}
BigInt operator/=(BigInt &a,BigInt b)
{
    BigInt c;
    BigInt_divide(a,b,c);
    return a=c;
}
BigInt operator%(BigInt a,BigInt b)
{
    BigInt t1,t2;
    BigInt_divide(a,b,t1);
    BigInt_times(t1,b,t2);
    BigInt_minus(a,t2,t1);
    return t1;
}
BigInt operator%=(BigInt &a,BigInt b)
{
    BigInt t1,t2;
    BigInt_divide(a,b,t1);
    BigInt_times(t1,b,t2);
    BigInt_minus(a,t2,t1);
    return a=t1;
}
void free_pointers()//Releasing temporary memory
{
    while(Mems.size()>0)
    {
        delete[] Mems.front();
        Mems.pop();
    }
}
//======================/
#endif

//stream input and output
#ifdef _GLIBCXX_OSTREAM
std::ostream& operator<<(std::ostream& str,BigInt n)
{
    n.format();
    if(n.nAn) str<<"nan";
    else
        str<<n.c_str();
    return str;
}
#endif

#ifdef _GLIBCXX_ISTREAM
std::istream& operator>>(std::istream& str,BigInt &n)
{
    cache.clear();
    while(!str.eof()&&!(str.peek()=='-'||(str.peek()>='0'&&str.peek()<='9')))
        str.get();
    bool flag=0;
    while(!str.eof()&&str.peek()=='-') flag=!flag,str.get();
    if(flag) cache.push('-');
    while(!str.eof()&&str.peek()>='0'&&str.peek()<='9') cache.push(str.get());
    char *p=new char[cache.size()+1],*t;
    memset(p,0,cache.size()+1);
    t=p;
    while(cache.size()>0) *t++=cache.front(),cache.pop();
    n=p;
    delete[] p;
    return str;
}
#endif//以上的高精度代码摘自我自己编写的一个高精度库。
using namespace std;
int T;
BigInt n,res;//定义大型整数类; 
int main()
{
#ifdef local
    //freopen("pro.in","r",stdin);
#endif
//    cin>>T;
//    while(T-->0)
//    {
//        cin>>n;
//        res=(n*(n*(n*(n-6)+23)-18)+24)/24;
//        /*
//        优化计算,原式为
//        (n*n*n*n-6*n*n*n+23*n*n-18*n+24)/24
//        */
//        cout<<res<<endl;
//    }
     cin>>n>>res;
     res=n;
     cout<<res;
    return 0;
}