Сложная длинная арифметика

Материал из Олимпиадное программирование в УлГТУ
Перейти к навигации Перейти к поиску

Более эффективные длинные целые

class PrintHelper {
    int d[1000], size;
public:
    PrintHelper() {
        d[0] = 0;
        size = 1;
    }
    void add1() {
        d[0]++;
    }
    void mul2() {
        int carry = 0;
        for (int i = 0; i < size; i++) {
            int x = d[i] * 2 + carry;
            d[i] = x % 10;
            carry = x / 10;
        }
        if (carry)
            d[size++] = 1;
    }
    void print() const {
        for (int i = size - 1; i >= 0; i--)
            printf("%d", d[i]);
        printf("\n");
    }
};

class BigInteger {
    static const int MAX_SIZE = 100;
    static const unsigned int MASK = ~(1 << 31);
    unsigned int d[MAX_SIZE];
    int size;
public:
    BigInteger(unsigned long long val = 0) {
        for (int i = 0; i < MAX_SIZE; i++)
            d[i] = 0;
        size = 0;
        if (val == 0)
            d[size++] = 0;
        while (val > 0) {
            d[size++] = val & MASK;
            val >>= 31;
        }
    }
    void print() const {
        PrintHelper p;
        for (int i = size - 1; i >= 0; i--) {
            for (int bit = 30; bit >= 0; bit--) {
                p.mul2();
                if ((d[i] >> bit) & 1)
                    p.add1();
            }
        }
        p.print();
    }
    int cmp(const BigInteger &that) const {
        if (size != that.size)
            return size < that.size ? -1 : 1;
        for (int i = size - 1; i >= 0; i--) {
            if (d[i] != that.d[i])
                return d[i] < that.d[i] ? -1 : 1;
        }
        return 0;
    }
    bool operator < (const BigInteger &that) const {
        return cmp(that) < 0;
    }
    bool operator == (const BigInteger &that) const {
        return cmp(that) == 0;
    }
    BigInteger &operator += (const BigInteger &that) {
        unsigned int carry = 0;
        for (int i = 0; i < max(size, that.size) || carry != 0; i++) {
            unsigned long long x = 0ULL + d[i] + that.d[i] + carry;
            d[i] = x & MASK;
            carry = x >> 31;
        }
        size = max(size, that.size) + 1;
        while (size > 1 && d[size - 1] == 0)
            size--;
        return *this;
    }
    BigInteger operator + (const BigInteger &that) const {
        BigInteger res = *this;
        return res += that;
    }
    BigInteger &operator -= (const BigInteger &that) {
        int carry = 0;
        for (int i = 0; i < size || carry != 0; i++) {
            long long x = 0LL + d[i] - that.d[i] + carry;
            d[i] = (x + (1ULL << 31)) & MASK;
            carry = x < 0 ? -1 : 0;
        }
        while (size > 1 && d[size - 1] == 0)
            size--;
        return *this;
    }
    BigInteger operator - (const BigInteger &that) const {
        BigInteger res = *this;
        return res -= that;
    }
    BigInteger &operator *= (const BigInteger &that) {
        unsigned int rd[MAX_SIZE] = {};
        for (int i = 0; i < size; i++) {
            unsigned int carry = 0;
            for (int j = 0; j < that.size || carry != 0; j++) {
                unsigned long long x = rd[i + j] + 1ULL * d[i] * that.d[j] + carry;
                rd[i + j] = x & MASK;
                carry = x >> 31;
            }
        }
        for (int i = 0; i < MAX_SIZE; i++)
            d[i] = rd[i];
        size = size + that.size;
        while (size > 1 && d[size - 1] == 0)
            size--;
        return *this;
    }
    BigInteger operator * (const BigInteger &that) const {
        BigInteger res = *this;
        return res *= that;
    }
    BigInteger &operator *= (unsigned int that) {
        unsigned int carry = 0;
        for (int i = 0; i < size || carry != 0; i++) {
            unsigned long long x = 1ULL * d[i] * that + carry;
            d[i] = x & MASK;
            carry = x >> 31;
        }
        size = size + 1;
        while (size > 1 && d[size - 1] == 0)
            size--;
        return *this;
    }
    BigInteger operator * (unsigned int that) const {
        BigInteger res = *this;
        return res *= that;
    }
    BigInteger &operator /= (const BigInteger &that) {
        BigInteger carry;
        for (int i = size - 1; i >= 0; i--) {
            carry *= (1ULL << 31);
            carry.d[0] = d[i];
            unsigned int l = 0, r = (1 << 31), m;
            while (l + 1 < r) {
                m = l + (r - l) / 2;
                if ((that * m).cmp(carry) <= 0)
                    l = m;
                else
                    r = m;
            }
            d[i] = l;
            carry = carry - that * d[i];
        }
        while (size > 1 && d[size - 1] == 0)
            size--;
        return *this;
    }
    BigInteger operator / (const BigInteger &that) const {
        BigInteger res = *this;
        return res /= that;
    }
    BigInteger operator % (const BigInteger &that) const {
        BigInteger carry;
        for (int i = size - 1; i >= 0; i--) {
            carry *= (1ULL << 31);
            carry.d[0] = d[i];
            unsigned int l = 0, r = (1 << 31), m;
            while (l + 1 < r) {
                m = l + (r - l) / 2;
                if ((that * m).cmp(carry) <= 0)
                    l = m;
                else
                    r = m;
            }
            unsigned int digit = l;
            carry = carry - that * digit;
        }
        return carry;
    }
    BigInteger gcd(const BigInteger &that) const {
        if (that == 0)
            return *this;
        return that.gcd(*this % that);
    }
};

Длинные целые со знаком

class BigSignedInteger {
    BigInteger a;
    int sgn;
    BigSignedInteger(const BigInteger &a, int sign) : a(a), sgn(sign) {}
public:
    BigSignedInteger(long long val = 0) {
        a = ::abs(val);
        sgn = val ? val > 0 ? 1 : -1 : 0;
    }
    BigSignedInteger(const BigInteger &val) {
        a = val;
        sgn = val.cmp(0);
    }
    void print() const {
        if (sgn == -1)
            printf("-");
        a.print();
    }
    BigInteger abs() const {
        return a;
    }
    int sign() const {
        return sgn;
    }
    int cmp(const BigSignedInteger &that) const {
        if (sgn != that.sgn)
            return sgn < that.sgn ? -1 : 1;
        return sgn * a.cmp(that.a);
    }
    bool operator < (const BigSignedInteger &that) const {
        return cmp(that) < 0;
    }
    bool operator == (const BigSignedInteger &that) const {
        return cmp(that) == 0;
    }
    BigSignedInteger operator + (const BigSignedInteger &that) const {
        if (sgn == 1) {
            if (that.sgn == 1)
                return BigSignedInteger(a + that.a, 1);
            if (that.sgn == 0)
                return *this;
            if (that.sgn == -1) {
                if (a > that.a)
                    return BigSignedInteger(a - that.a, 1);
                if (a == that.a)
                    return 0;
                if (a < that.a)
                    return BigSignedInteger(that.a - a, -1);
            }
        }
        if (sgn == 0) {
            return that;
        }
        if (sgn == -1) {
            if (that.sgn == 1) {
                if (a > that.a)
                    return BigSignedInteger(a - that.a, -1);
                if (a == that.a)
                    return 0;
                if (a < that.a)
                    return BigSignedInteger(that.a - a, 1);
            }
            if (that.sgn == 0)
                return *this;
            if (that.sgn == -1)
                return BigSignedInteger(a + that.a, -1);
        }
    }
    BigSignedInteger operator - (const BigSignedInteger &that) const {
        if (sgn == 1) {
            if (that.sgn == 1) {
                if (a > that.a)
                    return BigSignedInteger(a - that.a, 1);
                if (a == that.a)
                    return 0;
                if (a < that.a)
                    return BigSignedInteger(that.a - a, -1);
            }
            if (that.sgn == 0)
                return *this;
            if (that.sgn == -1)
                return BigSignedInteger(a + that.a, 1);
        }
        if (sgn == 0) {
            return BigSignedInteger(that.abs(), -that.sign());
        }
        if (sgn == -1) {
            if (that.sgn == 1)
                return BigSignedInteger(a + that.a, -1);
            if (that.sgn == 0)
                return *this;
            if (that.sgn == -1) {
                if (a > that.a)
                    return BigSignedInteger(a - that.a, -1);
                if (a == that.a)
                    return 0;
                if (a < that.a)
                    return BigSignedInteger(that.a - a, 1);
            }
        }
    }
    BigSignedInteger operator * (const BigSignedInteger &that) const {
        return BigSignedInteger(a * that.a, sgn * that.sgn);
    }
    BigSignedInteger operator / (const BigSignedInteger &that) const {
        if (a < that.a)
            return 0;
        return BigSignedInteger(a / that.a, sgn / that.sgn);
    }
};

Длинные рациональные числа со знаком

class BigRational {
    BigSignedInteger n;
    BigInteger d;
    void normalize() {
        BigInteger g = n.abs().gcd(d);
        n = n / g;
        d = d / g;
    }
public:
    BigRational(long long n = 0, long long d = 1) : n(n), d(d) {
        normalize();
    }
    BigRational(const BigSignedInteger &n, const BigInteger &d) : n(n), d(d) {
        normalize();
    }
    BigSignedInteger numerator() const {
        return n;
    }
    int cmp(const BigRational &that) const {
        return (n * that.d).cmp(that.n * d);
    }
    bool operator < (const BigRational &that) const {
        return cmp(that) < 0;
    }
    bool operator == (const BigRational &that) const {
        return cmp(that) == 0;
    }
    BigRational operator + (const BigRational &that) const {
        return BigRational(n * that.d + that.n * d, d * that.d);
    }
    BigRational operator - (const BigRational &that) const {
        return BigRational(n * that.d - that.n * d, d * that.d);
    }
    BigRational operator * (const BigRational &that) const {
        return BigRational(n * that.n, d * that.d);
    }
    BigRational operator / (const BigRational &that) const {
        if (that.n.sign() == 1)
            return BigRational(n * that.d, that.n.abs() * d);
        if (that.n.sign() == -1)
            return BigRational(n * that.d * -1, that.n.abs() * d);
    }
};