码迷,mamicode.com
首页 > 其他好文 > 详细

BIG INT

时间:2016-08-05 19:29:13      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:

/*
    Name: Big int
    Copyright: free
    Author: No Name
    Date: 17/04/16 13:40
    Description: Big int
*/
#include <iostream>
#include <iomanip>
#include <string>
#include <windows.h>
#include <conio.h>
#define ull unsigned long long
const ull INT_e18=1000000000000000000,INT_2=2000000000000000000,
          INT_4=4000000000000000000,INT_8=8000000000000000000,
          F_32=0xffffffff;
#define inlbinto inline bigint operator
//BIG_SIZE must belong to {4,6,8,10,12,14...}
const int BIG_SIZE=2048;
const int BIG_1=BIG_SIZE-1;
const int OUT_SIZE=((((BIG_SIZE*15/14)>>2)+1)<<2);
const int OUT_1=OUT_SIZE-1;
using namespace std;

class bigint {
        friend ostream& operator<<(ostream& out, bigint& x);
        friend istream& operator>>(istream& in,bigint& x);
    public:
        bigint () {
            ;
        };
        bigint (const bigint& b) {
            for(int i=BIG_SIZE; i;) {
                num[--i]=b.num[i];
            }
        }
        bigint (const ull& n) {
            ull* i=num+BIG_1;
            *i=n;
            while(i!=num) (*(--i))=0;
        }
        inline  ull &operator [](unsigned pos) {
            return num[pos];
        }
        inline  bigint &operator =(const bigint& b_int) {
            for(unsigned i=BIG_SIZE; --i;) num[i]=b_int.num[i];
            num[0]=b_int.num[0];
            return *this;
        }
        inline  bigint &operator =(const ull &_ull_int) {
            ull* i=num+BIG_1;
            *i=_ull_int;
            while(i!=num) (*(--i))=0;
            return *this;
        }
        inline  bigint &operator =(string& str) {
            *this=0;
            unsigned end=str.size();
            for(unsigned i=0; i!=end&&0<=str[i]&&str[i]>=9; ++i) {
                (*this).mult_ul(10);
                (*this)+=((unsigned long long)(str[i]-48));
            }
            return *this;
        }

        inline  bigint &operator <<=(unsigned step) {
            if(step>=64) {
                l_move64(step>>6);
                step&=63;
            }
            unsigned _st_=64-step;
            ull a=0,b=0;
            for(ull* i=num+BIG_SIZE; i!=num;) {
                a=(*(--i)>>_st_);
                *i<<=step;
                *i|=b;
                b=((*--i)>>_st_);
                *i<<=step;
                *i|=a;
            }
            return *this;
        }
        inline  bigint &operator >>=(unsigned step) {
            if(step>=64) {
                r_move64(step>>6);
                step&=63;
            }
            unsigned _st_=64-step;
            ull a=0,b=0;
            for(int i=-1; i!=BIG_1;) {
                a=(num[++i]<<_st_);
                num[i]>>=step;
                num[i]|=b;
                b=(num[++i]<<_st_);
                num[i]>>=step;
                num[i]|=a;
            }
            return *this;
        }
        inlbinto <<(unsigned step) {
            bigint b=*this;
            b<<=step;
            return b;
        }
        inlbinto >>(unsigned step) {
            bigint b=*this;
            b>>=step;
            return b;
        }
        inline  bigint &operator &=(const bigint &b) {
            for(unsigned i=BIG_SIZE; i;) num[--i]&=b.num[i];
            return *this;
        }
        inline  bigint &operator |=(const bigint &b) {
            for(unsigned i=BIG_SIZE; i;) num[--i]|=b.num[i];
            return *this;
        }
        inline  bigint &operator ^=(const bigint &b) {
            for(unsigned i=BIG_SIZE; i;) num[--i]^=b.num[i];
            return *this;
        }
        inlbinto &(const bigint &b) {
            bigint a=*this;
            a&=b;
            return a;
        }
        inlbinto |(const bigint &b) {
            bigint a=*this;
            a|=b;
            return a;
        }
        inlbinto ^(const bigint &b) {
            bigint a=*this;
            a^=b;
            return a;
        }

        inline  bigint &operator +=(const bigint& b_int) {
            for(unsigned i=BIG_SIZE; i;) {
                num[--i]+=b_int.num[i];
                if(num[i]<b_int.num[i]) while(!++num[--i]);
            }
            return *this;
        }
        inline  bigint &operator +=(const ull &_ullint) {
            if((num[BIG_1]+=_ullint)<_ullint) {
                for(unsigned i=BIG_1; !++num[--i];);
            }
            return *this;
        }
        inlbinto +(const bigint &b_int) {
            bigint r=*this;
            r+=b_int;
            return r;
        }
        inlbinto +(const ull &_ullint) {
            bigint r=*this;
            r+=_ullint;
            return r;
        }
        inline  bigint &operator ++() {
            for(ull* i=num+BIG_SIZE; !++(*(--i)););
            return *this;
        }
        inline  bigint operator ++(int) {
            bigint old=*this;
            for(ull* i=old.num+BIG_SIZE; !++(*(--i)););
            return old;
        }

        inline  bigint &operator -=(const bigint &b_int) {
            unsigned j;
            for(unsigned i=BIG_SIZE; i;) {
                if(num[--i]<(num[i]-=b_int.num[i])) while(~--num[--i]);
            }
            return *this;
        }
        inline  bigint &operator -=(const ull _ullint) {
            if(num[BIG_1]<num[BIG_1]-_ullint) for(unsigned i=BIG_1; ~--num[--i];);
            return *this;
        }
        inlbinto -(const bigint &b_int) {
            bigint r=*this;
            r-=b_int;
            return r;
        }
        inlbinto -(const ull _ullint) {
            bigint r=*this;
            r-=_ullint;
            return r;
        }
        inline  bigint &operator --() {
            for(unsigned i=BIG_SIZE; ~--num[--i];);
            return *this;
        }
        inline  bigint operator --(int) {
            bigint old=*this;
            for(unsigned i=BIG_SIZE; ~--num[--i];);
            return old;
        }

        inline  bigint &operator *=(const ull& that) {
            if(that>F_32) {
                bigint c;
                c=*this;
                (*this).mult_ul(that>>32);
                *this<<=32;
                c.mult_ul(that&0xffffffff);
                *this+=c;
                return *this;
            } else mult_ul(that);
        }

        inlbinto * (ull that) {
            bigint b=*this;
            return b*=that;
        }
        inline  bigint divi_ul(const ull ula) {
            ull b,c=0,d=0;/*
            从高位到低位,与上次未除残留c一同取余b, 除,  加已除残留d
            对b进行"%""/ "
            */
            for(unsigned i=0; i!=BIG_SIZE; ++i) {
                b=(num[i]%ula+c%ula);
                num[i]=(num[i]/ula+c/ula);
                if(b>=ula) {
                    ++num[i];
                    b-=ula;
                }
                if((num[i]+=d)<d) ++(num[i-1]);
                b<<=32;
                c=(b%ula);
                c<<=32;
                d=(b/ula);
                d<<=32;
            }
            return *this;
        }

//  BELOW METHODS ARE DEVELOPING!!!  DEVELOPING!!!  DEVELOPING!!!
        inlbinto / (bigint b);
        inline  bigint &operator /= (bigint b) {
            unsigned i=0;
            bigint c;
            c=*this;
            *this=0;
            while(i!=BIG_SIZE) {
                if(b[i]) break;
                ++i;
            }
            b.l_move64(i);
            i<<=6;
            if(!b[0]&0xffffffff00000000) i+=32;
            if(!b[0]&0xffff000000000000) i+=16;
            if(!b[0]&0xff00000000000000) i+=8;
            if(!b[0]&0xf000000000000000) i+=4;
            if(!b[0]&0x3000000000000000) i+=2;
            if(!b[0]&0x8000000000000000) ++i;
            b<<=(i&63);
            ++i;
            while(--i) {
                *this<<=1;
                if(b<c) {
                    c-=b;
                    num[BIG_1]|=1;
                }
                b>>=1;
            }
            if(b<c) num[BIG_1]|=1;
            return *this;
        }
        inlbinto / (ull b);
        inline  bigint &operator /= (ull b) {
            *this-=(*this%b);
            unsigned i;
            if(!(b&0xffffffff)) b>>=32;
            i+=32;
            if(!(b&0xffff)) b>>=16;
            i+=16;
            if(!(b&0xff)) b>>=8;
            i+=8;
            if(!(b&15)) b>>=4;
            i+=4;
            if(!(b&3)) b>>=2;
            i+=2;
            if(!(b&1)) b>>=1;
            ++i;
            *this>>=i;
        }
        inlbinto % (bigint b);
        inline  bigint &operator %= (bigint b) {
            unsigned i=0;
            while(i!=BIG_SIZE) {
                if(b[i]) break;
                ++i;
            }
            b.l_move64(i);
            i<<=6;
            if(!b[0]&0xffffffff00000000) i+=32;
            if(!b[0]&0xffff000000000000) i+=16;
            if(!b[0]&0xff00000000000000) i+=8;
            if(!b[0]&0xf000000000000000) i+=4;
            if(!b[0]&0x3000000000000000) i+=2;
            if(!b[0]&0x8000000000000000) ++i;
            b<<=(i&63);
            ++i;
            cout<<b;
            while(--i) {
                if(b<*this) {
                    *this-=b;
                    cout<<"as";
                }

                b>>=1;
            }
            if(b<*this) *this-=b;

            return *this;
        }
        inline  bigint &operator %= (const ull& that) {
            for(unsigned i=31; --i;) {
                num[0]%=that;
                *this<<=32;
            }
            num[0]%=that;
            return *this;
        }
        inlbinto % (ull that) {
            bigint a=*this;
            a%=that;
            return a;
        }
        inlbinto *=(const bigint &b);
        inlbinto *(const bigint &b);
//OK???

        inline  bool operator <(bigint b) {
            for(unsigned i=0; i!=BIG_SIZE; ++i) {
                if(num[i]<b.num[i]) return true;
                else if(num[i]==b.num[i]) continue;
                else return false;
            }
            return false;
        }
        inline  bool operator >(bigint b) {
            return b<*this;
        }
        inline  bool operator ==(bigint b) {
            for(unsigned i=BIG_SIZE; i;) {
                if(num[--i]!=b.num[i]) return false;
            }
            return true;
        }
        inline  bool operator !=(bigint b) {
            for(unsigned i=BIG_SIZE; i;) {
                if(num[--i]!=b.num[i]) return true;
            }
            return false;
        }
        //private:
        ull num[BIG_SIZE];
        inline  bigint &l_move64(unsigned step) {
            unsigned _st_=BIG_SIZE-step,i=0;
            for(; i!=_st_; ++i) {
                num[i]=num[i+step];
            }
            while(i!=BIG_SIZE) {
                num[i]=0;
                ++i;
            }
        }
        inline  bigint &mult_ul(const unsigned long that) {
            ull a=0,b=0,c=0;
            for(ull *i=num+BIG_SIZE; i!=num;) {
                (a=((*--i)>>32))*=that;
                ((*i)&=F_32)*=that;
                b=(a>>32);
                a<<=32;
                if(((*i+=c)+=a)<a) ++b;

                (a=((*--i)>>32))*=that;
                ((*i)&=F_32)*=that;
                c=(a>>32);
                a<<=32;
                if(((*i+=b)+=a)<a) ++c;
            }

            return *this;
        }
        inline  bigint &r_move64(unsigned step) {
            unsigned _st_=BIG_SIZE-step,i=BIG_SIZE;
            for(; i!=step; i) {
                num[--i]=num[i-step];
            }
            while(i) {
                num[--i]=0;
            }
        }


};

ostream& operator<<(ostream& out,bigint& x) {
    ull outint[OUT_SIZE]= {};
    int t;
    ull cx,h1,h2,*n,*i=x.num,*end=i+BIG_SIZE,*endo=outint+OUT_SIZE;
    while((!(*i))&&i<end) ++i;
    for(; i!=end; ++i) {
        cx=*i;
        for(t=17; --t;) {
            h2=0;
            for(n=endo; n!=outint;) {
                *(--n)<<=4;
                h1=0;
                if(*n>=INT_8) {
                    h1|=8;
                    (*n)-=INT_8;
                }
                if(*n>=INT_4) {
                    h1|=4;
                    (*n)-=INT_4;
                }
                if(*n>=INT_2) {
                    h1|=2;
                    (*n)-=INT_2;
                }
                if(*n>=INT_e18) {
                    h1|=1;
                    (*n)-=INT_e18;
                }
                (*n)|=h2;

                *(--n)<<=4;
                h2=0;
                if(*n>=INT_8) {
                    h2|=8;
                    *n-=INT_8;
                }
                if(*n>=INT_4) {
                    h2|=4;
                    *n-=INT_4;
                }
                if(*n>=INT_2) {
                    h2|=2;
                    *n-=INT_2;
                }
                if(*n>=INT_e18) {
                    h2|=1;
                    *n-=INT_e18;
                }
                (*n)|=h1;
            }


            *(endo-1)|=(cx>>60);
            cx<<=4;
        }
    }
    for(n=outint-1; (++n!=endo)&&(!(*n)););
    if(n==endo) --n;
    out<<(*n);
    out.fill(0);
    while(++n!=endo) cout<<setw(18)<<*n;
    return out;
}
istream& operator>>(istream& in,bigint &x) {
    char str[OUT_SIZE]= {};
    in>>str;
    unsigned end;
    for(end=0; str[end]; ++end);
    x=0;
    for(unsigned i=0; i!=end; ++i) {
        x*=10;
        x+=(str[i]-48);
    }
    return in;
}

bigint mult(const bigint &a,const unsigned long &b) {
    bigint r;
    r=a;
    r.mult_ul(b);
    return r;
}
unsigned long mod(const bigint &a,const ull &b) {
    ull r=0;
    for(unsigned i=0; i!=BIG_1; ++i) {
        r+=(a.num[i]%b);
        r%=b;
        r<<=32;
        r%=b;
        r<<=32;
        r%=b;
    }
    r+=(a.num[BIG_1]%b);
    r%=b;
    return (unsigned long) r;
}
bigint divi(const bigint &a,const unsigned long &b) {
    bigint r;
    r=a;
    return r.divi_ul(b);
}

bigint fact(ull n) {
    bigint r=1;
    ull i=1;
    if(n%2) {
        r=n;
        --n;
    }
    while(n>i) {
        r.mult_ul(n*i);
        --n;
        ++i;
    }
    return r;
}
bigint nCr(ull x,ull y) {
    if(x-y>y) y=x-y;

    ull a=x-y;
    ++x;
    bigint b=1;
    if(a&1) b=--x;
    if(a&2) b*=((--x)*(--x));
    while(--x>y) {
        b*=((x)*(--x));
        b*=((--x)*(--x));
    }
    if(a&1) {
        b.divi_ul(a);
        --a;
    }
    while(a) {
        (x=a)*=(--a);
        b.divi_ul(x);
        --a;
    }
    return b;
}

int main(){
    bigint a;unsigned long b;
    while(true){
        cin>>a>>b;
        a.divi_ul(b);
        cout<<a<<endl;
    }
}

#undef ull
#undef inlbinto

 

BIG INT

标签:

原文地址:http://www.cnblogs.com/TheName/p/5742395.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!