某科学的高精度板子

#define LL long long
#define MOD 1000000000
#define BUFFER_SIZE 100000
 
#define __base_t vector <int>
 
namespace __BigInt_b
{
string convert_s(const __base_t &a)
{
    static char buffer[BUFFER_SIZE]; char *ptr = buffer;
    ptr += sprintf(ptr, "%d", a[a.size() - 1]);
    for (int i = a.size() - 2; ~i; -- i)
        ptr += sprintf(ptr, "%09d", a[i]);
    string res(buffer);
    return res;
}
 
__base_t convert_b(const string &a)
{
    __base_t c; c.resize((a.size() + 8) / 9);
    for (int i = a.size() - 1, j = 1; ~i; -- i, j = (j * 10 == MOD? 1: j * 10))
        c[(a.size() - i - 1) / 9] += (a[i] - '0') * j;
    return c;
}
 
LL convert_i(const __base_t &a)
{
    LL b = 1, c = 0;
    for (int i = 0; i < a.size(); ++ i)
        c += a[i] * b, b = b * MOD;
    return c;
}
 
__base_t convert_b(LL a)
{
    __base_t b;
    if (a == 0) b.push_back(0);
    while (a) b.push_back(a % MOD), a /= MOD;
    return b;
}
 
int __comp(const __base_t &a, const __base_t &b)
{
    if (a.size() != b.size()) return a.size() < b.size()? -1: 1;
    for (int i = a.size() - 1; ~i; -- i)
        if (a[i] != b[i]) return a[i] < b[i]? -1: 1;
    return 0;
}
 
__base_t addi(const __base_t &a, const __base_t &b)
{
    if (a.size() < b.size()) return addi(b, a);
    __base_t c = a; c.push_back(0);
    for (int i = 0; i < b.size() || c[i] >= MOD; ++ i)
    {
        if (i < b.size()) c[i] += b[i];
        if (c[i] >= MOD) c[i] -= MOD, c[i + 1] ++;
    }
    while (c.size() > 1 && !c[c.size() - 1]) c.pop_back();
    return c;
}
 
__base_t subt(const __base_t &a, const __base_t &b)
{
    __base_t c = a;
    for (int i = 0; i < a.size() && (i < b.size() || c[i] < 0); ++ i)
    {
        if (i < b.size()) c[i] -= b[i];
        if (c[i] < 0)
            c[i] += MOD, c[i + 1] --;
    }
    while (c.size() > 1 && !c[c.size() - 1]) c.pop_back();
    return c;
}
 
__base_t mult(const __base_t &a, const __base_t &b)
{
    __base_t c; c.resize(a.size() + b.size() + 1);
    LL k = 0;
    for (int i = 0; i < a.size(); ++ i)
    {
        for (int j = 0; j < b.size(); ++ j)
        {
            k = k + 1ll * a[i] * b[j] + c[i + j];
            c[i + j] = k % MOD;
            k /= MOD;
        }
        c[i + b.size()] = k;
        k = 0;
    }
    while (c.size() > 1 && !c[c.size() - 1]) c.pop_back();
    return c;
}
 
void trial_division(const __base_t &a, int b, __base_t &c, int &d)
{
    c.resize(a.size());
    LL k = 0;
    for (int i = a.size() - 1; ~i; -- i)
    {
        k = k * MOD + a[i];
        c[i] = k / b;
        k %= b;
    }
    while (c.size() > 1 && !c[c.size() - 1]) c.pop_back();
    d = k;
}
 
__base_t divi(const __base_t &a, int b)
{
    __base_t c; int d;
    trial_division(a, b, c, d);
    return c;
}
 
int modu(const __base_t &a, int b)
{
    __base_t c; int d;
    trial_division(a, b, c, d);
    return d;
}
 
#define __trial_division_subt()\
{\
    LL k = 0;\
    for (int j = 0; j < b.size(); ++ j)\
    {\
        k = k - 1ll * p * b[j] + d[i + j];\
        d[i + j] = k % MOD;\
        k /= MOD;\
        if (d[i + j] < 0) d[i + j] += MOD, k --;\
    }\
    if (k) d[i + b.size()] += k;\
    c[i] += p;\
}
#define __get_val(x, y, z) (10ull * MOD * ((y) + 1 < (z)? x[(y) + 1]: 0) + 10ull * x[(y)] + ((y) - 1 >= 0? x[(y) - 1]: 0) / (MOD / 10))
void trial_division(const __base_t &a, const __base_t &b, __base_t &c, __base_t &d)
{
    if (a.size() < b.size())
    {
        c.resize(0);
        d = a;
        return;
    }
    c, d = a; c.clear(); c.resize(a.size() - b.size() + 1);
    for (int i = a.size() - b.size(); ~i; -- i)
    {
        int p;
        while (p = __get_val(d, i + (int)b.size() - 1, d.size()) / (__get_val(b, (int)b.size() - 1, b.size()) + 1), p)
            __trial_division_subt();
        p = 1;
        for (int j = b.size() - 1; ~j; -- j) if (d[j + i] != b[j])
        {
            p = b[j] < d[j + i];
            break;
        }
        if (p) __trial_division_subt();
    }
    while (c.size() > 1 && !c[c.size() - 1]) c.pop_back();
    while (d.size() > 1 && !d[d.size() - 1]) d.pop_back();
}
 
__base_t divi(const __base_t &a, const __base_t &b)
{
    __base_t c, d;
    trial_division(a, b, c, d);
    return c;
}
 
__base_t modu(const __base_t &a, const __base_t &b)
{
    __base_t c, d;
    trial_division(a, b, c, d);
    return d;
}
}
 
 
struct BigInt
{
    bool is_neg;
    __base_t data;
 
    BigInt() {}
    BigInt(LL x)
    {
        is_neg = x < 0; data = __BigInt_b::convert_b(abs(x));
    }
 
    BigInt(const string &x)
    {
        if (x[0] == '-') is_neg = 1, data = __BigInt_b::convert_b(x.substr(1, x.size() - 1));
        else is_neg = 0, data = __BigInt_b::convert_b(x);
    }
 
    string to_string() const
    {
        if (data.size() == 1 && data[0] == 0) return "0";
        else return (is_neg? "-": "") + __BigInt_b::convert_s(data);
    }
 
    LL to_int() const
    {
        return (is_neg? -1: 1) * __BigInt_b::convert_i(data);
    }
 
    BigInt operator + (const BigInt &b) const;
    BigInt operator - (const BigInt &b) const;
    template <typename T> BigInt & operator += (const T &b);
    template <typename T> BigInt & operator -= (const T &b);
    template <typename T> BigInt & operator *= (const T &b);
    template <typename T> BigInt & operator /= (const T &b);
    template <typename T> BigInt & operator %= (const T &b);
 
    BigInt & operator /= (int b);
 
};
 
ostream & operator << (ostream &out, const BigInt &x)
{
    out << x.to_string(); return out;
}
 
istream & operator >> (istream &in, BigInt &x)
{
    string t;
    in >> t;
    x = (BigInt)t;
    return in;
}
 
bool operator == (const BigInt &a, const BigInt &b) {if (a.is_neg != b.is_neg) return 0; return __BigInt_b::__comp(a.data, b.data) == 0;}
bool operator != (const BigInt &a, const BigInt &b) {if (a.is_neg != b.is_neg) return 1; return __BigInt_b::__comp(a.data, b.data) != 0;}
bool operator < (const BigInt &a, const BigInt &b) {if (a.is_neg != b.is_neg) return a.is_neg; return __BigInt_b::__comp(a.data, b.data) * (a.is_neg ? -1 : 1) < 0;}
bool operator > (const BigInt &a, const BigInt &b) {if (a.is_neg != b.is_neg) return !a.is_neg; return __BigInt_b::__comp(a.data, b.data) * (a.is_neg ? -1 : 1) > 0;}
bool operator <= (const BigInt &a, const BigInt &b) {if (a.is_neg != b.is_neg) return a.is_neg; return __BigInt_b::__comp(a.data, b.data) * (a.is_neg ? -1 : 1) <= 0;}
bool operator >= (const BigInt &a, const BigInt &b) {if (a.is_neg != b.is_neg) return !a.is_neg; return __BigInt_b::__comp(a.data, b.data) * (a.is_neg ? -1 : 1) >= 0;}
 
BigInt link(bool _is_neg, const __base_t &_data)
{
    BigInt c; c.is_neg = _is_neg; c.data = _data; if (_data.size() == 1 && _data[0] == 0) c.is_neg = 0; return c;
}
 
BigInt BigInt::operator + (const BigInt &b) const
{
    if (is_neg ^ b.is_neg)
    {
        if (__BigInt_b::__comp(data, b.data) >= 0) return link(is_neg, __BigInt_b::subt(data, b.data));
        else return link(b.is_neg, __BigInt_b::subt(b.data, data));
    }
    else return link(is_neg, __BigInt_b::addi(b.data, data));
}
 
BigInt BigInt::operator - (const BigInt &b) const
{
    if (is_neg ^ b.is_neg) return link(is_neg, __BigInt_b::addi(b.data, data));
    else
    {
        if (__BigInt_b::__comp(data, b.data) >= 0) return link(is_neg, __BigInt_b::subt(data, b.data));
        else return link(!is_neg, __BigInt_b::subt(b.data, data));
    }
}
 
BigInt operator * (const BigInt &a, const BigInt &b) {return link(a.is_neg ^ b.is_neg, __BigInt_b::mult(a.data, b.data));}
BigInt operator / (const BigInt &a, int b) {return link(a.is_neg ^ (b < 0? 1: 0), __BigInt_b::divi(a.data, abs(b)));}
int operator % (const BigInt &a, int b) {return (a.is_neg? -1: 1) * __BigInt_b::modu(a.data, abs(b));}
BigInt operator / (const BigInt &a, const BigInt &b) {return link(a.is_neg ^ b.is_neg, __BigInt_b::divi(a.data, b.data));}
BigInt operator % (const BigInt &a, const BigInt &b) {return link(a.is_neg, __BigInt_b::modu(a.data, b.data));}
 
#define __ext_opt(opt, __opt)\
template <typename T> BigInt operator opt (const T &a, const BigInt &b) { return (BigInt)(a) opt b;}\
template <typename T> BigInt operator opt (const BigInt &a, const T &b) { return a opt (BigInt)(b);}\
template <typename T> BigInt & BigInt::operator __opt (const T &b) {*this = *this opt (BigInt)b; return *this;}
 
__ext_opt(+, +=)
__ext_opt(-, -=)
__ext_opt(*, *=)
__ext_opt(/, /=)
__ext_opt(%, %=)
 
BigInt & BigInt::operator /= (int b) {*this = *this / b; return *this;}
 
#undef LL
#undef MOD
#undef __base_t
#undef __ext_opt
View Code
posted @ 2018-07-12 22:27  Yuhuger  阅读(208)  评论(0编辑  收藏  举报