50分,求助

P1009 [NOIP1998 普及组] 阶乘之和

JjHh @ 2024-05-22 21:56:52

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
int n;
LL res;
int main() {
    cin >> n;
    LL f = 1;
    for (int i = 1; i <= n; i++) {
        f *= i;
        res += f;
    }
    cout << res ;
    return 0;
}

by OIerWu_829 @ 2024-05-22 22:05:24

@JjHh 看 tag,高精度。


by qazsedcrfvgyhnujijn @ 2024-05-22 22:40:12

高精度
不嫌麻烦可以写一个高精度类,重载一堆运算符之后再做这道题
比如(当然其中很多用不到):

//无敌高精度板子(牛顿迭代+位压+开根+FFT+倍增除法+手动分配空间)
//支持高精加,高精减,高精乘(普通),高精乘(FFT),高精除,高精模,高精快速幂,高精取模快速幂,高精开根,高精abs,高精相反数
#ifndef BIGINTEGER_H
#define BIGINTEGER_H

#include <cmath>
#include <vector>
#include <sstream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <algorithm>

class BigInteger {
protected:
    using digit_t = long long;

    static const int WIDTH = 9;
    static const digit_t BASE = 1e9;
    static const long long FFT_LIMIT = 10000;

    digit_t* digits;
    long capacity, size;
    bool flag;

    inline void push(const digit_t&);
    inline void pop();

    inline int compare(const BigInteger&) const;

    static inline BigInteger fft_mul(const BigInteger&, const BigInteger&);
    inline BigInteger move(const long long&);
    static inline BigInteger inverse(const BigInteger&);

public:
    inline void reserve(const long&);

protected:
    inline void resize(const long&);

public:
    BigInteger() : digits(nullptr), flag(true) {*this = 0;}

    BigInteger(const BigInteger& x) : digits(nullptr) {*this = x;}
    BigInteger(const long long& x) : digits(nullptr) {*this = x;}
    BigInteger(const std::string& s) : digits(nullptr) {*this = s;}

    BigInteger& operator= (const BigInteger&);
    BigInteger& operator= (const long long&);
    BigInteger& operator= (const std::string&);

    ~BigInteger() {
        if (digits != nullptr) delete[] digits, digits = nullptr;
    }

    friend std::ostream& operator << (std::ostream& out, const BigInteger& x) {
        if (!x.flag) out << '-';
        out << (long long) x.digits[x.size];
        for (int i = x.size - 1; i >= 1; i--) 
            out << std::setw(WIDTH) << std::setfill('0') << (long long) x.digits[i];
        return out;
    }
    friend std::istream& operator >> (std::istream& in, BigInteger& x) {
        std::string s; in >> s; x = s; 
        return in;
    }

    std::string to_string() const;

    BigInteger operator- () const;
    BigInteger abs() const;

    bool operator< (const BigInteger&) const;
    bool operator> (const BigInteger&) const; 
    bool operator== (const BigInteger&) const; 
    bool operator!= (const BigInteger&) const;
    bool operator<= (const BigInteger&) const;
    bool operator>= (const BigInteger&) const;

    BigInteger operator+ (const BigInteger&) const;
    BigInteger operator- (const BigInteger&) const;
    BigInteger operator* (const BigInteger&) const;
    BigInteger operator/ (const long long&) const;
    BigInteger operator/ (const BigInteger&) const;
    BigInteger operator% (const long long&) const;
    BigInteger operator% (const BigInteger&) const;

    BigInteger pow(const long long&) const;
    BigInteger pow(const long long&, const BigInteger&) const;

    BigInteger sqrt(const long long& = 2) const;

    BigInteger& operator+= (const BigInteger&);
    BigInteger& operator-= (const BigInteger&);
    BigInteger& operator*= (const BigInteger&);
    BigInteger& operator/= (const long long&);
    BigInteger& operator/= (const BigInteger&);
    BigInteger& operator%= (const long long&);
    BigInteger& operator%= (const BigInteger&);
};

inline void BigInteger::push(const digit_t& val) {
    if (capacity == size) {
        long new_capacity = 0;
        if (capacity < 1000) new_capacity = capacity << 1;
        else new_capacity = (new_capacity >> 1) * 3;
        digit_t* new_digits = new digit_t[new_capacity + 1];
        std::memcpy(new_digits, digits, sizeof(long long) * (capacity + 1));
        delete[] digits;
        digits = new_digits, capacity = new_capacity, ++size;
        return;
    }
    digits[++size] = val;
}
inline void BigInteger::pop() {digits[size--] = 0;}

inline int BigInteger::compare(const BigInteger& x) const {
    if (flag && !x.flag) return 1;
    if (!flag && x.flag) return -1;

    int sgn = (flag && x.flag ? 1 : -1);
    if (size > x.size) return sgn;
    if (size < x.size) return -sgn;

    for (int i = size; i >= 1; i--) {
        if (digits[i] > x.digits[i]) return sgn;
        if (digits[i] < x.digits[i]) return -sgn;
    }
    return 0;
}

inline void BigInteger::reserve(const long& sz) {
    if (digits != nullptr) delete[] digits;
    capacity = sz, size = 0;
    digits = new digit_t[sz + 1];
    std::memset(digits, 0, sizeof(digit_t) * (sz + 1));
}
inline void BigInteger::resize(const long& sz) {
    reserve(sz), size = sz;
}

BigInteger& BigInteger::operator= (const BigInteger& x) {
    reserve(x.size + 1);
    flag = x.flag, size = x.size;
    std::memcpy(digits, x.digits, sizeof(digit_t) * (x.size + 1));
    return *this;
}
BigInteger& BigInteger::operator= (const long long& x) {
    flag = x >= 0;
    reserve(12);
    if (x == 0) {
        digits[1] = 0;
        return *this;
    }
    if (x == LLONG_MIN) return *this = "-9223372036854775808";
    long long n = std::abs(x);
    do {
        push(n % BASE);
        n /= BASE;
    } while (n);
    return *this;
}
BigInteger& BigInteger::operator= (const std::string& s) {
    flag = true, reserve(s.size() / WIDTH + 1);
    if (s.empty() || s == "-") return *this = 0;
    int i = 0;
    if (s[0] == '-') flag = false, i++;
    for (int j = s.size() - 1; j >= i; j -= WIDTH) {
        int start = std::max(i, j - WIDTH + 1), len = j - start + 1;
        push(std::stoi(s.substr(start, len)));
    }
    return *this;
}

std::string BigInteger::to_string() const {
    std::stringstream ss; ss << *this;
    return ss.str();
}

BigInteger BigInteger::operator- () const {
    BigInteger res = *this;
    res.flag = !flag;
    return res;
}
BigInteger BigInteger::abs() const {
    BigInteger res = *this;
    res.flag = true;
    return res;
}

bool BigInteger::operator< (const BigInteger& x) const {return compare(x) < 0;}
bool BigInteger::operator> (const BigInteger& x) const {return compare(x) > 0;}
bool BigInteger::operator== (const BigInteger& x) const {return compare(x) == 0;}
bool BigInteger::operator!= (const BigInteger& x) const {return compare(x) != 0;}
bool BigInteger::operator<= (const BigInteger& x) const {return compare(x) <= 0;}
bool BigInteger::operator>= (const BigInteger& x) const {return compare(x) >= 0;}

BigInteger BigInteger::operator+ (const BigInteger& x) const {
    if (!x.flag) return *this - x.abs();
    if (!flag) return x - abs();

    BigInteger res; 
    res.flag = !(flag ^ x.flag);
    int n = std::max(size, x.size) + 1;
    res.reserve(n);
    digit_t carry = 0;
    for (int i = 1; i <= n; i++) {
        digit_t d1 = i <= size ? digits[i] : 0, d2 = i <= x.size ? x.digits[i] : 0;
        res.push(d1 + d2 + carry);
        carry = res.digits[i] / BASE;
        res.digits[i] %= BASE;
    }
    while (res.size > 1 && res.digits[res.size] == 0) res.pop();
    return res;
}
BigInteger BigInteger::operator- (const BigInteger& x) const {
    if (!x.flag) return *this + x.abs();
    if (!flag) return -(abs() + x);
    BigInteger res;
    if (*this < x) res.flag = false;
    digit_t carry = 0;
    int n = std::max(size, x.size);
    res.reserve(n);
    for (int i = 1; i <= n; i++) {
        digit_t d1 = i <= size ? digits[i] : 0, d2 = i <= x.size ? x.digits[i] : 0;
        if (res.flag) res.push(d1 - d2 - carry);
        else res.push(d2 - d1 - carry);
        if (res.digits[i] < 0) res.digits[i] += BASE, carry = 1;
        else carry = 0;
    }
    while (res.size > 1 && res.digits[res.size] == 0) res.pop();
    return res;
}

namespace BigInteger_FFT {
    constexpr long double PI = std::acos(-1.0L);

    struct complex {
        long double real, imag;

        complex(long double x = 0.0, long double y = 0.0) : real(x), imag(y) {}

        complex operator + (const complex& other) const {
            return complex(real + other.real, imag + other.imag);
        }
        complex operator - (const complex& other) const {
            return complex(real - other.real, imag - other.imag);
        }
        complex operator * (const complex& other) const {
            return complex(real * other.real - imag * other.imag, real * other.imag + other.real * imag);
        }
        complex conj() const {
            return complex(real, -imag);
        }
    };

    complex* arr = nullptr;

    inline void init(int n) {
        if (arr != nullptr) delete[] arr, arr = nullptr;
        arr = new complex[n + 1];
        for (int i = 0; i <= n; i++) arr[i] = complex(0.0, 0.0);
    }

    inline void fft(complex* a, long len) {
        for (long i = len; i >= 2; i >>= 1) {
            complex wn(std::cos(2.0L * PI / i), std::sin(2.0L * PI / i));
            for (long j = 0; j < len; j += i) {
                complex w(1.0, 0.0);
                for (long k = j; k < j + (i >> 1); k++, w = w * wn) {
                    complex u = a[k], t = a[k + (i >> 1)];
                    a[k] = u + t, a[k + (i >> 1)] = w * (u - t);
                }
            }
        }
    }
    inline void idft(complex* a, long len) {
        for (long i = 2; i <= len; i <<= 1) {
            complex wn(std::cos(2.0L * PI / i), std::sin(2.0L * PI / i));
            for (long j = 0; j < len; j += i) {
                complex w(1.0, 0.0);
                for (long k = j; k < j + (i >> 1); k++, w = w * wn) {
                    complex u = a[k], t = w * a[k + (i >> 1)];
                    a[k] = u + t, a[k + (i >> 1)] = u - t;
                }
            }
        }
    }
}

BigInteger BigInteger::fft_mul(const BigInteger& a, const BigInteger& b) {
    long lim = 1;
    while (lim <= 3 * (a.size + b.size)) lim <<= 1;
    BigInteger_FFT::init(lim);
    using BigInteger_FFT::arr;
    for (int i = 0; i < a.size; i++) {
        arr[i * 3].real = a.digits[i + 1] % 1000;
        arr[i * 3 + 1].real = a.digits[i + 1] / 1000 % 1000;
        arr[i * 3 + 2].real = a.digits[i + 1] / (1000 * 1000);
    }
    for (int i = 0; i < b.size; i++) {
        arr[i * 3].imag = b.digits[i + 1] % 1000;
        arr[i * 3 + 1].imag = b.digits[i + 1] / 1000 % 1000;
        arr[i * 3 + 2].imag = b.digits[i + 1] / (1000 * 1000);
    }
    BigInteger_FFT::fft(arr, lim);
    for (int i = 0; i < lim; i++) arr[i] = (arr[i] * arr[i]).conj();
    BigInteger_FFT::idft(arr, lim);
    BigInteger res;
    res.resize(a.size + b.size + 1);
    digit_t carry = 0;
    for (int i = 0; i <= a.size + b.size; i++) {
        carry += (digit_t)(arr[i * 3].imag * -0.5 / lim + 0.5);
        carry += (digit_t)(arr[i * 3 + 1].imag * -0.5 / lim + 0.5) * 1000LL;
        carry += (digit_t)(arr[i * 3 + 2].imag * -0.5 / lim + 0.5) * 1000LL * 1000LL;
        res.digits[i + 1] += carry % BASE, carry /= BASE;
    }
    while (res.size > 1 && res.digits[res.size] == 0) res.pop();
    return res;
} 

BigInteger BigInteger::operator* (const BigInteger& x) const {
    BigInteger zero = 0;
    if (*this == zero || x == zero) return zero;
    int n = size, m = x.size;
    if (1LL * n * m >= 1) {
        BigInteger res = fft_mul(*this, x);
        res.flag = !(flag ^ x.flag);
        return res;
    }

    BigInteger res;
    res.flag = !(flag ^ x.flag);
    res.resize(n + m + 2);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            res.digits[i + j - 1] += digits[i] * x.digits[j];
            res.digits[i + j] += res.digits[i + j - 1] / BASE;
            res.digits[i + j - 1] %= BASE;
        }
    }
    for (int i = 1; i <= n + m + 1; i++) {
        res.digits[i + 1] += res.digits[i] / BASE;
        res.digits[i] %= BASE;
    }
    while (res.size > 1 && res.digits[res.size] == 0) res.pop();
    return res;
}

BigInteger BigInteger::operator/ (const long long& x) const {
    if (x == 0) throw -1;
    if (*this == 0) return 0;
    BigInteger res;
    res.flag = !(flag ^ (x >= 0));

    digit_t cur = 0, div = std::abs(x);
    res.resize(size);

    for (int i = size; i >= 1; i--) {
        cur = cur * BASE + digits[i];
        res.digits[i] = res.flag ? (cur / div) : (-cur / -div);
        cur %= div;
    }
    while (res.size > 1 && res.digits[res.size] == 0) res.pop();
    return res;
}

BigInteger BigInteger::operator/ (const BigInteger& x) const {
    static std::vector<BigInteger> pow2 = {1};
    static std::vector<BigInteger> estimate;
    estimate.clear();
    if (*this < x) return 0;
    BigInteger cur = x;
    while (cur <= *this) {
        estimate.emplace_back(cur), cur += cur;
        if (estimate.size() > pow2.size()) pow2.emplace_back(pow2.back() + pow2.back());
    }
    if (cur == *this) {
        pow2.back().flag = !(flag ^ x.flag);
        return BigInteger(pow2.back());
    }
    BigInteger res = pow2[estimate.size() - 1];
    cur = estimate.back();
    for (long i = estimate.size() - 1; i >= 0; i--) {
        if (cur + estimate[i] <= *this) cur += estimate[i], res += pow2[i];
    }
    res.flag = !(flag ^ x.flag);
    return res;
}

BigInteger BigInteger::operator% (const long long& x) const {
    if (x == 2) return digits[1] & 1;
    return *this - (*this / x * x);
} 
BigInteger BigInteger::operator% (const BigInteger& x) const {
    return *this - (*this / x * x);
} 

BigInteger BigInteger::pow(const long long& x) const {
    BigInteger res = 1, a = *this;
    for (long long t = x; t != 0; t >>= 1) {
        if (t & 1) res *= a;
        a *= a;
    }
    return res;
}
BigInteger BigInteger::pow(const long long& x, const BigInteger& p) const {
    BigInteger res = 1, a = *this % p;
    for (long long t = x; t != 0; t >>= 1) {
        if (t & 1) res = res * a % p;
        a = a * a % p;
    }
    return res;
}

BigInteger BigInteger::sqrt(const long long& x) const {
    BigInteger l = 0, r = 1;
    while (r.pow(x) <= *this) l = r, r += r;
    while (l + 1 < r) {
        BigInteger mid = (l + r) / 2;
        if (mid.pow(x) <= *this) l = mid;
        else r = mid;
    }
    return l.pow(x) <= *this ? l : r;
}

BigInteger& BigInteger::operator+= (const BigInteger& x) {return *this = *this + x;}
BigInteger& BigInteger::operator-= (const BigInteger& x) {return *this = *this - x;}
BigInteger& BigInteger::operator*= (const BigInteger& x) {return *this = *this * x;}
BigInteger& BigInteger::operator/= (const long long& x) {return *this = *this / x;}
BigInteger& BigInteger::operator/= (const BigInteger& x) {return *this = *this / x;}
BigInteger& BigInteger::operator%= (const long long& x) {return *this = *this / x;}
BigInteger& BigInteger::operator%= (const BigInteger& x) {return *this = *this % x;}

#endif //BIGINTEGER_H

然后该怎么写就怎么写,把类型名换成 BigInteger 就行了


by JjHh @ 2024-05-25 13:00:44

@hhy517090 谢谢已经AC了


|