列表

详情


NC251510. math

描述

题目背景

兄弟会背叛你,女人会离开你,金钱会诱惑你,生活会刁难你,只有数学不会,不会就是不会,怎么学都不会。

题意简述 

给出 n,令 f(i)=\sum_{j=0}^{i}(-1)^j(i+j)!\binom{i}{j}\binom{n}{i+j}
\bigoplus_{i=0}^{n}(f_i \mod 1000000007)

输入描述

一行一个整数 n

输出描述

一行一个整数表示答案。

示例1

输入:

233

输出:

458525574

示例2

输入:

9910032

输出:

883301329

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 1282ms, 内存消耗: 276256K, 提交时间: 2023-08-12 10:16:31

#include <bits/stdc++.h>
using namespace std;

constexpr int P = 1e9 + 7;

template <class T> T qp(T a, int b) {
    T c{1};
    for (; b; b /= 2, a *= a) {
        if (b % 2) {
            c *= a;
        }
    }
    return c;
}

struct mint {
    int x;
    mint(int _x = 0) : x(_x % P) { x < 0 ? x += P : 0; }
    int val() const { return x; }

    mint operator - () const {
        return -x;
    }
    mint inv() const {
        assert(x != 0);
        return qp(*this, P - 2);
    }
    mint &operator += (const mint &rhs) {
        x += rhs.x - P, x += x >> 31 & P;
        return *this;
    }
    mint &operator -= (const mint &rhs) {
        x -= rhs.x, x += x >> 31 & P;
        return *this;
    }
    mint &operator *= (const mint &rhs) {
        x = (long long)x * rhs.x % P;
        return *this;
    }
    mint &operator /= (const mint &rhs) {
        return *this *= rhs.inv();
    }
    friend mint operator + (mint lhs, const mint &rhs) {
        return lhs += rhs;
    }
    friend mint operator - (mint lhs, const mint &rhs) {
        return lhs -= rhs;
    }
    friend mint operator * (mint lhs, const mint &rhs) {
        return lhs *= rhs;
    }
    friend mint operator / (mint lhs, const mint &rhs) {
        return lhs /= rhs;
    }

    friend ostream &operator << (ostream &os, const mint &a) {
        return os << a.val();
    }
};

struct _comb {
    int n;
    vector<mint> _fact, _finv, _inv;

    _comb() : n{0}, _fact{1}, _finv{1}, _inv{0} {}
    _comb(int n) : _comb() { initt(n); }

    void initt(int m) {
        if (m <= n) return;
        _fact.resize(m + 1);
        _finv.resize(m + 1);
        _inv.resize(m + 1);

        for (int i = n + 1; i <= m; i++) {
            _fact[i] = _fact[i - 1] * i;
        }
        _finv[m] = _fact[m].inv();
        for (int i = m; i > n; i--) {
            _finv[i - 1] = _finv[i] * i;
            _inv[i] = _finv[i] * _fact[i - 1];
        }
        n = m;
    }

    mint fact(int m) {
        if (m > n) initt(2 * m);
        return _fact[m];
    }
    mint finv(int m) {
        if (m > n) initt(2 * m);
        return _finv[m];
    }
    mint inv(int m) {
        if (m > n) initt(2 * m);
        return _inv[m];
    }
    mint binom(int n, int m) {
        if (n < m || m < 0) return 0;
        return fact(n) * finv(m) * finv(n - m);
    }
} comb;

auto find_rec(const vector<mint> &a, int deg) {
    const int n = a.size();
    const int B = (n + 2) / (deg + 2), C = B * (deg + 1), R = n - (B - 1);
    assert(B >= 2 && R >= C - 1);
    vector mat(R, vector<mint>(C));
    for (int i = 0; i < R; i++) {
        for (int j = 0; j < B; j++) {
            mint x = a[i + j];
            for (int k = 0; k <= deg; k++) {
                mat[i][j * (deg + 1) + k] = x;
                x *= i + j;
            }
        }
    }
    int c = 0;
    for (int i = 0; i < C; i++) {
        int p = -1;
        for (int j = c; j < R; j++) {
            if (mat[j][i].val()) {
                p = j;
                break;
            }
        }
        if (p == -1) {
            break;
        }
        swap(mat[p], mat[c]);
        mint w = mat[c][c].inv();
        for (int j = i; j < C; j++) {
            mat[c][j] *= w;
        }
        for (int j = c + 1; j < R; j++) {
            if (mat[j][i].val()) {
                mint t = mat[j][i];
                for (int k = i; k < C; k++) {
                    mat[j][k] -= t * mat[i][k];
                }
            }
        }
        c++;
    }
    assert(c != C);
    for (int i = c - 1; i >= 0; i--) {
        if (mat[i][c].val()) {
            for (int j = i - 1; j >= 0; j--) {
                mat[j][c] -= mat[i][c] * mat[j][i];
            }
        }
    }
    int od = c / (deg + 1);
    vector res(od + 1, vector<mint>(deg + 1));
    res[0][c % (deg + 1)] = 1;
    for (int i = c - 1; i >= 0; i--) {
        res[od - i / (deg + 1)][i % (deg + 1)] = -mat[i][c];
    }
    for (int i = 0; i <= od; i++) {
        vector<mint> tmp(deg + 1);
        for (int k = 0; k <= deg; k++) {
            mint s = 1;
            for (int j = k; j <= deg; j++) {
                tmp[k] += s * res[i][j];
                s = s * -i * (j + 1) / (j + 1 - k);
            }
        }
        res[i] = tmp;
    }
    return res;
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    int n;
    cin >> n;
    vector<mint> f(20);
    for (int i = 0; i < f.size(); i++) {
        for (int j = 0; j <= i; j++) {
            f[i] += (j % 2 ? -1 : 1) * comb.fact(i + j) * comb.binom(i, j) * comb.binom(n, i + j);
        }
    }
    auto rec = find_rec(f, 2);
    while (f.size() <= n) {
        int i = f.size();
        mint lhs;
        for (int k = 1; k < rec.size(); k++) {
            mint pw = 1;
            for (int j = 0; j < rec[k].size(); j++) {
                lhs -= pw * f[i - k] * rec[k][j];
                pw *= i;
            }
        }
        mint rhs, pw = 1;
        for (int j = 0; j < rec[0].size(); j++) {
            rhs += pw * rec[0][j];
            pw *= i;
        }
        assert(rhs.val() == 1);
        f.push_back(lhs);
    }
    int xors = 0;
    for (int i = 0; i <= n; i++) {
        xors ^= f[i].val();
    }
    cout << xors << "\n";
    return 0;
}

上一题