1 条题解

  • 0
    @ 2026-10-27 12:58:43

    思路与算法

    递归函数solve(k)返回Hk。k=0、1直接返回基值;其他项按2xHk−1−2(k−1)Hk−2求出。用访问标记和数组保存结果,每个k只计算一次。结果使用带符号十进制大整数,支持加减与小整数乘法,最后附加.00。

    正确性说明

    基例与定义相同。假设所有更小下标的缓存值正确,递归取回Hk−1、Hk−2后严格应用定义,故Hk正确;缓存只复用已经计算的同一x、同一下标结果,不改变值。按强归纳,solve(n)返回精确多项式整数。大整数逐位进借位维护同一整数,不发生截断。

    复杂度

    设D为过程中最大整数的十进制位数,memo与标记初始化O(n),每个状态常数次O(D)大整数运算,总时间O(nD),缓存O(nD),递归栈O(n)。

    易错点

    Hn可负、可超64位,不能用无符号整数或只保留double。不能无缓存地重复展开两棵递归树。n=0是合法基例;输出整数后附.00,不是把大整数转浮点再格式化。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    struct cpp_int {
        string s;
        bool neg;
        cpp_int(long long v = 0) : s(to_string(v)), neg(v < 0) {
            if (neg)
                s.erase(s.begin());
        }
        void norm() {
            auto p = s.find_first_not_of('0');
            s = p == string::npos ? "0" : s.substr(p);
            if (s == "0")
                neg = false;
        }
        static int cmpabs(const cpp_int &a, const cpp_int &b) {
            if (a.s.size() != b.s.size())
                return a.s.size() < b.s.size() ? -1 : 1;
            return a.s == b.s ? 0 : a.s < b.s ? -1 : 1;
        }
        friend bool operator<(const cpp_int &a, const cpp_int &b) {
            if (a.neg != b.neg)
                return a.neg;
            int c = cmpabs(a, b);
            return a.neg ? c > 0 : c < 0;
        }
        friend bool operator==(const cpp_int &a, const cpp_int &b) {
            return a.neg == b.neg && a.s == b.s;
        }
        friend bool operator!=(const cpp_int &a, const cpp_int &b) {
            return !(a == b);
        }
        friend bool operator>(const cpp_int &a, const cpp_int &b) {
            return b < a;
        }
        friend bool operator<=(const cpp_int &a, const cpp_int &b) {
            return !(b < a);
        }
        friend bool operator>=(const cpp_int &a, const cpp_int &b) {
            return !(a < b);
        }
        cpp_int operator-() const {
            cpp_int r = *this;
            if (r.s != "0")
                r.neg = !r.neg;
            return r;
        }
        friend cpp_int operator+(const cpp_int &a, const cpp_int &b) {
            cpp_int r;
            r.s.clear();
            int carry = 0;
            if (a.neg == b.neg) {
                int i = (int)a.s.size() - 1, j = (int)b.s.size() - 1;
                while (i >= 0 || j >= 0 || carry) {
                    int v = carry + (i >= 0 ? a.s[i--] - '0' : 0) + (j >= 0 ? b.s[j--] - '0' : 0);
                    r.s += char('0' + v % 10);
                    carry = v / 10;
                }
                r.neg = a.neg;
            } else {
                const cpp_int *x = &a, *y = &b;
                if (cmpabs(a, b) < 0)
                    swap(x, y);
                int i = (int)x->s.size() - 1, j = (int)y->s.size() - 1;
                while (i >= 0) {
                    int v = x->s[i--] - '0' - carry - (j >= 0 ? y->s[j--] - '0' : 0);
                    carry = v < 0;
                    if (carry)
                        v += 10;
                    r.s += char('0' + v);
                }
                r.neg = x->neg;
            }
            reverse(r.s.begin(), r.s.end());
            r.norm();
            return r;
        }
        friend cpp_int operator-(const cpp_int &a, const cpp_int &b) {
            return a + (-b);
        }
        friend cpp_int operator*(const cpp_int &a, int b) {
            cpp_int r;
            r.s.clear();
            long long carry = 0;
            long long z = b;
            if (z < 0)
                z = -z;
            for (int i = (int)a.s.size() - 1; i >= 0; i--) {
                carry += (a.s[i] - '0') * z;
                r.s += char('0' + carry % 10);
                carry /= 10;
            }
            while (carry) {
                r.s += char('0' + carry % 10);
                carry /= 10;
            }
            reverse(r.s.begin(), r.s.end());
            r.neg = a.neg ^ (b < 0);
            r.norm();
            return r;
        }
        friend cpp_int operator/(const cpp_int &a, int b) {
            cpp_int r;
            r.s.clear();
            long long rem = 0, z = b;
            if (z < 0)
                z = -z;
            for (char c : a.s) {
                rem = rem * 10 + c - '0';
                r.s += char('0' + rem / z);
                rem %= z;
            }
            r.neg = a.neg ^ (b < 0);
            r.norm();
            return r;
        }
        cpp_int &operator+=(const cpp_int &b) {
            *this = *this + b;
            return *this;
        }
        cpp_int &operator-=(const cpp_int &b) {
            *this = *this - b;
            return *this;
        }
        cpp_int &operator*=(int b) {
            *this = *this * b;
            return *this;
        }
        friend istream &operator>>(istream &in, cpp_int &a) {
            string v;
            if (in >> v) {
                a.neg = v[0] == '-';
                if (v[0] == '-' || v[0] == '+')
                    v.erase(v.begin());
                a.s = v;
                a.norm();
            }
            return in;
        }
        friend ostream &operator<<(ostream &out, const cpp_int &a) {
            if (a.neg)
                out << '-';
            return out << a.s;
        }
    };
    
    vector<cpp_int> memo;
    vector<bool> seen;
    int x;
    cpp_int hermite(int n) {
        if (seen[n])
            return memo[n];
        seen[n] = true;
        if (n == 0)
            return memo[n] = 1;
        if (n == 1)
            return memo[n] = 2 * x;
        return memo[n] = hermite(n - 1) * (2 * x) - hermite(n - 2) * (2 * (n - 1));
    }
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        cin >> n >> x;
        memo.resize(n + 1);
        seen.resize(n + 1);
        cout << hermite(n) << ".00\n";
    }
    
    • 1

    信息

    ID
    2071
    时间
    1000ms
    内存
    64MiB
    难度
    普及
    标签
    递交数
    0
    已通过
    0
    上传者