高橋君 题解

AtCoder 天下一プログラマーコンテスト2014 本戦 高橋君

题意

给定 \(n, k\),求

\[\sum\limits_{i = 0}^{k}\dbinom{n}{i} \]

多测,\(1 \le n, k, T \le 10^5\)

题解

可以考虑使用莫队求解,下文讲述如何移动指针。

\(n \rightarrow n + 1\)

根据杨辉三角递推式 \(\dbinom{n}{m} = \dbinom{n - 1}{m} + \dbinom{n - 1}{m - 1}\) 可以得出

\[\begin{aligned} F(n + 1, m) &= \sum\limits_{i = 0}^{m} \dbinom{n + 1}{i} \\ &= \sum\limits_{i = 0}^{m} \left(\dbinom{n}{i} + \dbinom{n}{i - 1}\right) \\ &= 2\sum\limits_{i = 0}^{m} \dbinom{n}{i} - \dbinom{n}{m} \\ &= 2 \cdot F(n, m) - \dbinom{n}{m} \end{aligned}\]

\(m \rightarrow m + 1\)

\[\begin{aligned} F(n, m + 1) &= \sum\limits_{i = 0}^{m + 1} \dbinom{n}{i} \\ &= \sum\limits_{i = 0}^{m} \dbinom{n}{i} + \dbinom{n}{m + 1}\\ &= F(n, m) + \dbinom{n}{m + 1} \end{aligned}\]

这部分的复杂度为 \(\mathcal{O}(n \sqrt{n})\)

总复杂度 \(\mathcal{O}(n \sqrt{n})\),可以通过本题。

Code

#include <bits/stdc++.h>

typedef long long valueType;
typedef std::vector<valueType> ValueVector;
typedef ValueVector::iterator iterator;
typedef std::vector<iterator> IteratorVector;

constexpr valueType MOD = 1e9 + 7;

template<typename T1, typename T2, typename T3 = valueType>
void Inc(T1 &a, T2 b, const T3 &mod = MOD) {
    a = a + b;

    if (a >= mod)
        a -= mod;
}

template<typename T1, typename T2, typename T3 = valueType>
void Dec(T1 &a, T2 b, const T3 &mod = MOD) {
    a = a - b;

    if (a < 0)
        a += mod;
}

template<typename T1, typename T2, typename T3 = valueType>
T1 mul(T1 a, T2 b, const T3 &mod = MOD) {
    return (long long) a * b % mod;
}

template<typename T1, typename T2, typename T3 = valueType>
void Mul(T1 &a, T2 b, const T3 &mod = MOD) {
    a = (long long) a * b % mod;
}

template<typename T1, typename T2, typename T3 = valueType>
T1 pow(T1 a, T2 b, const T3 &mod = MOD) {
    T1 result = 1;

    while (b > 0) {
        if (b & 1)
            Mul(result, a, mod);

        Mul(a, a, mod);
        b = b >> 1;
    }

    return result;
}

namespace UU {
    valueType N, M;

    ValueVector Fact, InvFact, belong, ans;

    valueType C(valueType n, valueType m) {
        if (n < m)
            return 0;

        return mul(Fact[n], mul(InvFact[m], InvFact[n - m]));
    }

    struct Query {
        valueType n, m, id;

        Query(valueType n, valueType m, valueType id) : n(n), m(m), id(id) {}

        friend bool operator<(Query const &left, Query const &right) {
            if (belong[left.n] != belong[right.n])
                return belong[left.n] < belong[right.n];

            return left.m < right.m;
        }
    };

    std::vector<Query> query;

    void init(valueType n) {
        N = n;
        M = 0;

        Fact.resize(N + 1);
        InvFact.resize(N + 1);
        belong.resize(N + 1);

        valueType block = std::ceil(std::sqrt((double) N));

        for (valueType i = 1; i <= N; ++i)
            belong[i] = (i - 1) / block + 1;

        Fact[0] = 1;
        for (valueType i = 1; i <= N; ++i)
            Fact[i] = mul(Fact[i - 1], i);

        InvFact[N] = pow(Fact[N], MOD - 2);
        for (valueType i = N - 1; i >= 0; --i)
            InvFact[i] = mul(InvFact[i + 1], i + 1);
    }

    void add(valueType id, valueType n, valueType m) {
        query.emplace_back(n, m, id);
    }

    constexpr valueType Inv2 = (MOD + 1) / 2;

    void solve() {
        std::sort(query.begin(), query.end());

        M = (valueType) query.size();
        ans.resize(M);

        valueType nowN = 0, nowM = 0;
        valueType Ans = 1;

        for (auto const &iter : query) {
            while (nowM < iter.m) {
                ++nowM;

                Inc(Ans, C(nowN, nowM));
            }

            while (nowM > iter.m) {
                Dec(Ans, C(nowN, nowM));

                --nowM;
            }

            while (nowN < iter.n) {
                Mul(Ans, 2);
                Dec(Ans, C(nowN, nowM));

                ++nowN;
            }

            while (nowN > iter.n) {
                --nowN;

                Inc(Ans, C(nowN, nowM));
                Mul(Ans, Inv2);
            }

            ans[iter.id] = Ans;
        }
    }

    void output() {
        for (auto const &iter : ans)
            std::cout << iter << std::endl;
    }
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    valueType M;

    std::cin >> M;

    UU::init(1e5);

    for (valueType i = 0; i < M; ++i) {
        valueType n, m;

        std::cin >> n >> m;

        UU::add(i, n, m);
    }

    UU::solve();

    UU::output();

    return 0;
}
posted @ 2023-10-04 20:20  User-Unauthorized  阅读(13)  评论(0编辑  收藏  举报