zoukankan      html  css  js  c++  java
  • sroHOBOorz来自HOBO的高精类

    /*
     bigint()
     bigint(long long)
     bigint(bigint)
     bigint(char*)
     bigint(string)
     +, +=, ++
     -, -=, --
     *, *=
     /, /=
     <<, <<=
     ==, !=
     <, <=
     >, >=
     -
     !
     abs(bigint), bigint.abs()
     pow(bigint, unsigned), bigint.pow(unsigned)
     root(bigint, unsigned), bigint.root(unsigned)
     sqrt(bigint), bigint.sqrt()
     bigint.read(default = stdin)
     bigint.write(default = stdout)
     istream>>bigint
     ostream<<bigint
     enoughMemory() : optimize division and modulo
    */
    #include <iostream>
    
    #ifndef BIGINT
    #define BIGINT 1
    
    #include <istream>
    #include <ostream>
    #include <string>
    #include <vector>
    #include <complex>
    #include <algorithm>
    #include <utility>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    
    static const unsigned base = 10000, length = 4;
    static bool __enoughMemory = false;
    
    typedef vector<int> vi;
    typedef vector<int>::iterator viit;
    typedef vector<int>::const_iterator vicit;
    typedef vector<int>::reverse_iterator virit;
    typedef vector<int>::const_reverse_iterator vicrit;
    typedef complex<double> comp;
    typedef vector<comp> vc;
    typedef vector<comp>::iterator vcit;
    
    class Bigint {
    public :
        Bigint();
        template<typename _Tp> Bigint(_Tp);
        Bigint(const Bigint&);
        Bigint(const char*);
        Bigint(const string&);
        
        bool& neg();
        const bool& neg() const;
        vi& num();
        const vi& num() const;
        
        bool operator==(const Bigint&) const;
        bool operator!=(const Bigint&) const;
        bool operator<(const Bigint&) const;
        bool operator<=(const Bigint&) const;
        bool operator>(const Bigint&) const;
        bool operator>=(const Bigint&) const;
        
        Bigint& operator+=(const Bigint&);
        Bigint& operator-=(const Bigint&);
        Bigint& operator*=(const Bigint&);
        Bigint& operator/=(const Bigint&);
        Bigint& operator%=(const Bigint&);
        Bigint& operator<<=(const unsigned&);
        Bigint& operator>>=(const unsigned&);
        
        Bigint& operator++();
        Bigint& operator--();
        Bigint operator-() const;
        bool operator!() const;
        
        int compare(const Bigint&) const;
        bool equal(const Bigint&) const;
        bool less(const Bigint&) const;
        bool lessOrEqual(const Bigint&) const;
        bool greater(const Bigint&) const;
        bool greaterOrEqual(const Bigint&) const;
        
        Bigint& abs();
        Bigint& pow(unsigned);
        Bigint& root(const unsigned&);
        Bigint& sqrt();
        void multiply10(const unsigned&);
        void divide2();
        
        void add(const Bigint&);
        void subtract(const Bigint&);
        void multiply(const Bigint&);
        void multiplySlow(const Bigint&);
        void multiplyFast(const Bigint&, const int&, const int&);
        pair<vi, vi> divide(const Bigint&);
        
        Bigint& read(FILE*);
        const Bigint& write(FILE*) const;
        
    private :
        bool _m_neg;
        vi _m_num;
        
        void adjust();
        comp exp(const double&);
        void bitrev(const vcit&, const int&, const int&, const int&, const int&);
        void fft(vc&, const int&, const int&, const bool&);
        
        void divideByZero();
        void imaginaryNumberUnsupported();
        void error(const string&);
    };
    
    //pre-declaration
    Bigint abs(const Bigint&);
    Bigint pow(const Bigint&, const unsigned&);
    Bigint root(const Bigint&, const unsigned&);
    Bigint sqrt(const Bigint&);
    istream& operator>>(istream&, Bigint&);
    ostream& operator<<(ostream&, const Bigint&);
    void enoughMemory();
    
    //operator
    inline Bigint operator+(const Bigint& __x, const Bigint& __y) {
        return Bigint(__x) += __y;
    }
    inline Bigint operator-(const Bigint& __x, const Bigint& __y) {
        return Bigint(__x) -= __y;
    }
    inline Bigint operator*(const Bigint& __x, const Bigint& __y) {
        return Bigint(__x) *= __y;
    }
    inline Bigint operator/(const Bigint& __x, const Bigint& __y) {
        return Bigint(__x) /= __y;
    }
    inline Bigint operator%(const Bigint& __x, const Bigint& __y) {
        return Bigint(__x) %= __y;
    }
    template<typename _Tp> inline Bigint operator<<(const Bigint& __x, const _Tp& __y) {
        return Bigint(__x) <<= __y;
    }
    template<typename _Tp> inline Bigint operator>>(const Bigint& __x, const _Tp& __y) {
        return Bigint(__x) >>= __y;
    }
    
    //public
    
    //constructor
    inline Bigint::Bigint() {
        neg() = false;
        num().clear();
        num().push_back(0);
    }
    template<typename _Tp> inline Bigint::Bigint(_Tp __t) {
        if (__t < 0) neg() = true, __t = -__t;
        else neg() = false;
        num().clear();
        while (__t >= base) {
            num().push_back(__t % base);
            __t /= base;
        }
        num().push_back(__t);
    }
    inline Bigint::Bigint(const Bigint& __t) {
        *this = __t;
    }
    inline Bigint::Bigint(const char* __c) {
        while (*__c) {
            if (*__c == '-' || *__c == '+' || '0' <= *__c && *__c <= '9')
                break;
            ++__c;
        }
        if (*__c == '-') ++__c, neg() = true;
        else {
            neg() = false;
            if (*__c == '+') ++__c;
        }
        int __n = strlen(__c);
        num().clear();
        if (__n == 0) {
            neg() = false;
            num().push_back(0);
            return ;
        }
        const char* __t = __c + __n;
        while (__c + 1 != __t && *__c == '0') ++__c;
        int __x = 0, __y = 1, __z = 0;
        while (__t-- != __c) {
            if (__z == 4) {
                num().push_back(__x);
                __x = 0, __y = 1, __z = 0;
            }
            __x += (*__t - '0') * __y;
            __y = (__y << 3) + (__y << 1);
            ++__z;
        }
        num().push_back(__x);
    }
    inline Bigint::Bigint(const string& __s) {
        string::const_iterator i = __s.begin();
        string::const_iterator j = __s.end();
        while (i != j) {
            if (*i == '-' || *i == '+' || '0' <= *i && *i <= '9')
                break;
            ++i;
        }
        if (i != j) {
            if (*i == '-') ++i, neg() = true;
            else {
                neg() = false;
                if (*i == '+') ++i;
            }
        }
        int __n = j - i;
        if (__n == 0) {
            neg() = false;
            num().push_back(0);
            return ;
        }
        while (i + 1 != j && *i == '0') ++i;
        int __x = 0, __y = 1, __z = 0;
        while (j-- != i) {
            if (__z == 4) {
                num().push_back(__x);
                __x = 0, __y = 1, __z = 0;
            }
            __x += (*j - '0') * __y;
            __y = (__y << 3) + (__y << 1);
            ++__z;
        }
        num().push_back(__x);
    }
    
    inline bool& Bigint::neg() {
        return _m_neg;
    }
    inline const bool& Bigint::neg() const {
        return _m_neg;
    }
    inline vi& Bigint::num() {
        return _m_num;
    }
    inline const vi& Bigint::num() const {
        return _m_num;
    }
    
    //logical operator
    inline bool Bigint::operator==(const Bigint& __t) const {
        return neg() == __t.neg() && equal(__t);
    }
    inline bool Bigint::operator!=(const Bigint& __t) const {
        return neg() != __t.neg() || !equal(__t);
    }
    inline bool Bigint::operator<(const Bigint& __t) const {
        if (neg() != __t.neg()) return neg();
        if (neg()) return greater(__t);
        return less(__t);
    }
    inline bool Bigint::operator<=(const Bigint& __t) const {
        if (neg() != __t.neg()) return neg();
        if (neg()) return greaterOrEqual(__t);
        return lessOrEqual(__t);
    }
    inline bool Bigint::operator>(const Bigint& __t) const {
        if (neg() != __t.neg()) return __t.neg();
        if (neg()) return less(__t);
        return greater(__t);
    }
    inline bool Bigint::operator>=(const Bigint& __t) const {
        if (neg() != __t.neg()) return __t.neg();
        if (neg()) return lessOrEqual(__t);
        return greaterOrEqual(__t);
    }
    
    //arithmetic operators
    inline Bigint& Bigint::operator+=(const Bigint& __t) {
        if (neg() == __t.neg()) add(__t);
        else {
            int __x = compare(__t);
            if (__x == 0) *this = Bigint();
            else if (__x == -1) {
                Bigint __y = *this;
                *this = __t;
                subtract(__y);
            }
            else subtract(__t);
        }
        return *this;
    }
    inline Bigint& Bigint::operator-=(const Bigint& __t) {
        return *this += (-__t);
    }
    inline Bigint& Bigint::operator*=(const Bigint& __t) {
        if (*this != 0 && __t != 0) {
            neg() = neg() != __t.neg();
            multiply(__t);
        }
        else *this = Bigint();
        return *this;
    }
    inline Bigint& Bigint::operator/=(const Bigint& __t) {
        if (__t == 0) divideByZero();
        if (less(__t)) *this = Bigint();
        else {
            neg() = neg() != __t.neg();
            num() = divide(__t).first;
            adjust();
        }
        return *this;
    }
    inline Bigint& Bigint::operator%=(const Bigint& __t) {
        if (__t == 0) divideByZero();
        num() = divide(__t).second;
        adjust();
        if (num().size() == 1 && !*num().rbegin()) neg() = false;
        return *this;
    }
    inline Bigint& Bigint::operator<<=(const unsigned& __y) {
        return *this *= Bigint(2).pow(__y);
    }
    inline Bigint& Bigint::operator>>=(const unsigned& __y) {
        for (unsigned i = 0 ; i < __y ; ++i) divide2();
        return *this;
    }
    
    //self operator
    inline Bigint& Bigint::operator++() {
        return *this += 1;
    }
    inline Bigint& Bigint::operator--() {
        return *this -= 1;
    }
    inline Bigint Bigint::operator-() const {
        Bigint __t = *this;
        if (__t != 0) __t.neg() ^= true;
        return __t;
    }
    inline bool Bigint::operator!() const {
        return *this == 0;
    }
    
    //comparator
    inline int Bigint::compare(const Bigint& __t) const {
        if (num().size() < __t.num().size()) return -1;
        else if (num().size() > __t.num().size()) return 1;
        vicrit i = num().rbegin();
        vicrit j = __t.num().rbegin();
        while (i != num().rend()) {
            if (*i < *j) return -1;
            else if (*i > *j) return 1;
            ++i, ++j;
        }
        return 0;
    }
    inline bool Bigint::equal(const Bigint& __t) const {
        return compare(__t) == 0;
    }
    inline bool Bigint::less(const Bigint& __t) const {
        return compare(__t) == -1;
    }
    inline bool Bigint::lessOrEqual(const Bigint& __t) const {
        int __r = compare(__t);
        return __r == -1 || __r == 0;
    }
    inline bool Bigint::greater(const Bigint& __t) const {
        return compare(__t) == 1;
    }
    inline bool Bigint::greaterOrEqual(const Bigint& __t) const {
        int __r = compare(__t);
        return __r == 1 || __r == 0;
    }
    
    //math
    inline Bigint& Bigint::abs() {
        if (neg()) neg() = false;
        return *this;
    }
    inline Bigint& Bigint::pow(unsigned __y) {
        Bigint __x = *this;
        *this = 1;
        while (__y) {
            if (__y & 1) *this *= __x;
            __x *= __x;
            __y >>= 1;
        }
        return *this;
    }
    inline Bigint& Bigint::root(const unsigned& __y = 2) {
        if (!__y) divideByZero();
        if (*this == 0 || __y == 1) return *this;
        bool __n = neg();
        if (__n)
            if (__y & 1) neg() = false;
            else imaginaryNumberUnsupported();
        const double log2_10 = 3.3219280948873623478703194294893901758648313930245806;
        size_t __s = num().size();
        if (double(__s << 2) * log2_10 < __y) return *this = 1;
        __s = __s / __y + (__s % __y ? 1 : 0);
        int __l, __r, __m;
        Bigint __a = *this, __b, __c;
        num().clear();
        for (int i = __s - 1 ; i >= 0 ; --i) {
            __l = 1, __r = base - 1;
            while (__l <= __r) {
                __m = __l + __r >> 1;
                __b = *this;
                __b.num().insert(__b.num().begin(), __m);
                __b.pow(__y);
                __b.multiply10(i * __y << 2);
                if (__b <= __a) __l = __m + 1;
                else __r = __m - 1;
            }
            num().insert(num().begin(), __r);
        }
        neg() = __n;
        return *this;
    }
    inline Bigint& Bigint::sqrt() {
        root();
        return *this;
    }
    inline void Bigint::multiply10(const unsigned& __t) {
        if (!__t) return ;
        size_t __s = num().size();
        size_t __r = (__t >> 2) + (__t & 3 ? 1 : 0);
        int __x = 0, __y, __z, __a, __b;
        if ((__t & 3) == 0) __a = 1, __b = 10000;
        else if ((__t & 3) == 1) __a = 1000, __b = 10;
        else if ((__t & 3) == 2) __a = 100, __b = 100;
        else if ((__t & 3) == 3) __a = 10, __b = 1000;
        num().resize(__s + __r);
        virit i = num().rbegin();
        virit j = i + __r;
        while (i != num().rbegin() + __s) {
            __y = *j++;
            __z = __y / __a;
            __x += __z;
            *i++ = __x;
            __x = (__y - __z * __a) * __b;
        }
        *i++ = __x;
        fill(i, num().rend(), 0);
        adjust();
    }
    inline void Bigint::divide2() {
        int __t = 0;
        for (virit i = num().rbegin() ; i != num().rend() ; ++i) {
            __t = (__t & 1 ? base : 0) + *i;
            *i = __t >> 1;
        }
        adjust();
    }
    
    //+, -, *, /
    inline void Bigint::add(const Bigint& __t) {
        if (num().size() < __t.num().size())
            num().resize(__t.num().size());
        viit i = num().begin();
        vicit j = __t.num().begin();
        while (i != num().end() && j != __t.num().end())
            *i++ += *j++;
        for (i = num().begin() ; i + 1 != num().end() ; ++i)
            if (*i >= base) {
                *i -= base;
                ++*(i + 1);
            }
        if (*i >= base) {
            *i -= base;
            num().push_back(1);
        }
    }
    inline void Bigint::subtract(const Bigint& __t) {
        viit i = num().begin();
        vicit j = __t.num().begin();
        while (j != __t.num().end())
            *i++ -= *j++;
        for (i = num().begin() ; i + 1 != num().end() ; ++i)
            if (*i < 0) {
                *i += base;
                --*(i + 1);
            }
        adjust();
    }
    inline void Bigint::multiply(const Bigint& __t) {
        int __n = max(num().size(), __t.num().size());
        int __l = 0;
        while ((1 << __l) < __n) ++__l;
        __n = 1 << ++__l;
        if ((long long)num().size() * __t.num().size() <= (long long)__n * __l * 20)
            multiplySlow(__t);
        else
            multiplyFast(__t, __n, __l);
        adjust();
    }
    inline void Bigint::multiplySlow(const Bigint& __t) {
        int __n = num().size() + __t.num().size(), i, j, k;
        vi __x, __y;
        if (__t.num().size() * 4 < num().size())
            __x = __t.num(), __y = num();
        else
            __x = num(), __y = __t.num();
        num().clear();
        num().resize(__n);
        for (i = 0 ; i < __x.size() ; ++i) {
            k = __x[i];
            for (j = 0 ; j < __y.size() ; ++j)
                num()[i + j] += k * __y[j];
            k = i + 1 + __y.size();
            for (j = 0 ; j < k ; ++j) {
                num()[j + 1] += num()[j] / base;
                num()[j] %= base;
            }
        }
    }
    inline void Bigint::multiplyFast(const Bigint& __t, const int& __n, const int& __l) {
        vc a, b;
        a.reserve(__n);
        b.reserve(__n);
        for (viit i = num().begin() ; i != num().end() ; ++i)
            a.push_back(comp(*i, 0));
        for (vicit i = __t.num().begin() ; i != __t.num().end() ; ++i)
            b.push_back(comp(*i, 0));
        a.resize(__n);
        b.resize(__n);
        fft(a, __l, __n, true);
        fft(b, __l, __n, true);
        vcit i = a.begin(), j = b.begin();
        while (i != a.end()) *i++ *= *j++;
        fft(a, __l, __n, false);
        long long __x = 0;
        num().resize(__n);
        i = a.begin();
        viit k = num().begin();
        while (i != a.end()) {
            __x = (long long)(i++ ->real() / __n + 0.5) + __x / base;
            *k++ = __x % base;
        }
    }
    inline pair<vi, vi> Bigint::divide(const Bigint& __t) {
        int __l, __r, __m, __n = num().size() - __t.num().size() + 1;
        Bigint __x = *this, __y = __t, __z;
        vi __v;
        __v.resize(__n);
        if (__enoughMemory) {
            Bigint __p[10];
            for (__m = 0 ; __m < 10 ; ++__m) __p[__m] = __m * __y;
            for (int i = __n - 1 ; i >= 0 ; --i) {
                int k = 0;
                for (int j = 3 + (i << 2) ; j >= (i << 2) ; --j) {
                    __l = 1, __r = 9;
                    while (__l <= __r) {
                        __m = __l + __r >> 1;
                        __z = __p[__m];
                        __z.multiply10(j);
                        if (__z.greater(__x)) __r = __m - 1;
                        else __l = __m + 1;
                    }
                    k = (k << 3) + (k << 1) + __r;
                    __z = __p[__r];
                    __z.multiply10(j);
                    __x.subtract(__z);
                }
                __v[i] = k;
            }
        }
        else {
            for (int i = __n - 1 ; i >= 0 ; --i) {
                __l = 1, __r = base - 1;
                while (__l <= __r) {
                    __m = __l + __r >> 1;
                    __z = __m * __y;
                    __z.multiply10(i << 2);
                    if (__z.greater(__x)) __r = __m - 1;
                    else __l = __m + 1;
                }
                __v[i] = __r;
                __z = __r * __y;
                __z.multiply10(i << 2);
                __x.subtract(__z);
            }
        }
        return make_pair(__v, __x.num());
    }
    
    //io
    inline Bigint& Bigint::read(FILE *in = stdin) {
        string __s = "";
        char __c = fgetc(in);
        while (true) {
            if (__c == '-' || __c == '+' || '0' <= __c && __c <= '9' || __c == EOF)
                break;
            __c = fgetc(in);
        }
        while (true) {
            __s += __c;
            __c = fgetc(in);
            if (__c < '0' || __c > '9') break;
        }
        return *this = Bigint(__s.c_str());
    }
    inline const Bigint& Bigint::write(FILE *out = stdout) const {
        vicrit i = num().rbegin();
        if (neg()) fprintf(out, "-");
        fprintf(out, "%d", *i++);
        while (i != num().rend()) fprintf(out, "%04d", *i++);
        return *this;
    }
    
    //private
    
    //other
    inline void Bigint::adjust() {
        virit i = num().rbegin();
        while (i + 1 != num().rend()) {
            if (*i) break;
            ++i;
        }
        num().erase(i.base(), num().end());
    }
    inline comp Bigint::exp(const double& u) {
        return comp(cos(u), sin(u));
    }
    inline void Bigint::bitrev(const vcit& i, const int& __l, const int& __p, const int& __x, const int& __y) {
        if (__p == 0) {
            if (__x < __y) swap(*(i + __x), *(i + __y));
            return ;
        }
        bitrev(i, __l, __p - 1, __x << 1, __y);
        bitrev(i, __l, __p - 1, __x << 1 | 1, __y | (1 << __l - __p));
    }
    inline void Bigint::fft(vc& __a, const int& __l, const int& __n, const bool& __r) {
        const double __p = 3.141592653589793238462643383279;
        bitrev(__a.begin(), __l, __l, 0, 0);
        for (int i = 1 ; i <= __l ; ++i) {
            int __m = 1 << i;
            comp wm = exp((__r ? -2 : 2) * __p / __m);
            for (int k = 0 ; k < __n ; k += __m) {
                comp w = 1;
                for (int j = 0 ; j < __m / 2 ; ++j) {
                    comp t = w * __a[k + j + __m / 2];
                    comp u = __a[k + j];
                    __a[k + j] = u + t;
                    __a[k + j + __m / 2] = u - t;
                    w *= wm;
                }
            }
        }
    }
    
    //error
    inline void Bigint::divideByZero() {
        error("divide by zero");
    }
    inline void Bigint::imaginaryNumberUnsupported() {
        error("imaginary number unsupported");
    }
    inline void Bigint::error(const string& __s) {
        fprintf(stderr, "%s
    ", __s.c_str());
        cerr << __s << endl;
        abort();
    }
    
    //math
    inline Bigint abs(const Bigint& __x) {
        return Bigint(__x).abs();
    }
    inline Bigint pow(const Bigint& __x, const unsigned& __y) {
        return Bigint(__x).pow(__y);
    }
    inline Bigint root(const Bigint& __x, const unsigned& __y = 2) {
        return Bigint(__x).root(__y);
    }
    inline Bigint sqrt(const Bigint& __x) {
        return Bigint(__x).sqrt();
    }
    
    //io
    inline istream& operator>>(istream& __s, Bigint& __t) {
        string __r;
        __s >> __r;
        __t = Bigint(__r);
        return __s;
    }
    inline ostream& operator<<(ostream& __s, const Bigint& __t) {
        if (__t.neg()) __s << '-';
        vicrit i = __t.num().rbegin();
        __s << *i;
        while (++i != __t.num().rend()) {
            __s.width(length);
            __s.fill('0');
            __s << *i;
        }
        return __s;
    }
    
    //optimization
    inline void enoughMemory() {
        __enoughMemory = true;
    }
    
    #endif
    

      

  • 相关阅读:
    Android 进阶 Fragment 介绍和使用 (一)
    Android Activity 详述
    android 自定义组合控件 顶部导航栏
    android 开发进阶自定义控件 类似 TextView
    android 开发进阶 自定义控件-仿ios自动清除控件
    Android 在程序中动态添加 View 布局或控件
    Android ImageView 详述
    关于北京工作居住证相关问题
    Android中常用的5大布局详述
    关于北京计算机技术与软件专业技术资格(水平)考试(软考)报名及证书的领取
  • 原文地址:https://www.cnblogs.com/JackSlowFuck/p/4020264.html
Copyright © 2011-2022 走看看