結果

問題 No.829 成長関数インフレ中
ユーザー SuikabaSuikaba
提出日時 2019-05-04 16:41:51
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
TLE  
実行時間 -
コード長 7,665 bytes
コンパイル時間 3,562 ms
コンパイル使用メモリ 224,272 KB
実行使用メモリ 19,696 KB
最終ジャッジ日時 2023-09-05 05:41:28
合計ジャッジ時間 10,878 ms
ジャッジサーバーID
(参考情報)
judge12 / judge14
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
8,760 KB
testcase_01 AC 2 ms
4,380 KB
testcase_02 AC 2 ms
4,380 KB
testcase_03 AC 2 ms
4,380 KB
testcase_04 AC 2 ms
4,380 KB
testcase_05 AC 1 ms
4,376 KB
testcase_06 AC 2 ms
4,380 KB
testcase_07 AC 2 ms
4,380 KB
testcase_08 AC 2 ms
4,380 KB
testcase_09 AC 1 ms
4,388 KB
testcase_10 AC 1 ms
4,376 KB
testcase_11 AC 2 ms
4,376 KB
testcase_12 AC 59 ms
7,920 KB
testcase_13 AC 5 ms
4,380 KB
testcase_14 AC 40 ms
6,364 KB
testcase_15 AC 1,122 ms
8,672 KB
testcase_16 TLE -
testcase_17 TLE -
testcase_18 -- -
testcase_19 -- -
testcase_20 -- -
testcase_21 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

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

using ll = long long;

ll mod_inv(ll a, ll m) {
    ll b = m, u = 1, v = 0;
    while(b > 0) {
        ll t = a / b;
        a -= t * b; swap(a, b);
        u -= t * v; swap(u, v);
    }
    return (u % m + m) % m;
}

ll mod_pow(ll x, ll n, ll m) {
    ll res = 1;
    while(n > 0) {
        if(n & 1) (res *= x) %= m;
        (x *= x) %= m;
        n >>= 1;
    }
    return res;
}

// solve: find x which statisfies (x mod m[i]) == u[i]
// require: m[i] are co-prime
ll garner(std::vector<ll> m, std::vector<ll> u, int mod) {
    const int n = m.size();
    std::vector<ll> inv_prod(n);
    for(int i = 1; i < n; ++i) {
        ll prod = m[0] % m[i];
        for(int j = 1; j < i; ++j) {
            prod = (prod * m[j]) % m[i];
        }
        inv_prod[i] = mod_inv(prod, m[i]);
    }

    std::vector<ll> v(n);
    v[0] = u[0];
    for(int i = 1; i < n; ++i) {
        ll tmp = v[i - 1];
        for(int j = i - 2; j >= 0; --j) {
            tmp = (tmp * m[j] + v[j]) % m[i];
        }
        v[i] = ((u[i] - tmp) * inv_prod[i]) % m[i];
        if(v[i] < 0) v[i] += m[i];
    }

    ll res = v[n - 1];
    for(int i = n - 2; i >= 0; --i) {
        res = (res * m[i] + v[i]) % mod;
    }
    return res;
}

template <int Mod, bool IsPrime = false>
class mod_int {
    using ll = long long;

public:
    constexpr mod_int() : n(0) {}
    constexpr mod_int(int n_) : n(n_) {
        if(n >= Mod)     n %= Mod;
        else if(n < 0) n = (n % Mod + Mod) % Mod;
    }
    constexpr mod_int(ll n_) : n(n_) { n = (n + Mod) % Mod; }

    constexpr operator int() const { return n; }
    constexpr operator ll() const  { return n; }

    constexpr bool operator==(mod_int const& other) const { return n == other.n; }
    constexpr mod_int& operator+=(mod_int const& other) {
        if((n += other.n) >= Mod) n -= Mod;
        return *this;
    }
    constexpr mod_int& operator-=(mod_int const& other) {
        if((n += Mod - other.n) >= Mod) n -= Mod;
        return *this;
    }
    constexpr mod_int& operator*=(mod_int const& other) {
        n = (unsigned long long)n * other.n % Mod;
        return *this;
    }
    constexpr typename std::enable_if<IsPrime, mod_int>::type& operator/=(mod_int const& other) {
        return *this *= other.inverse();
    }
    constexpr mod_int operator+(mod_int other) const { return mod_int(*this) += other; }
    constexpr mod_int operator-(mod_int other) const { return mod_int(*this) -= other; }
    constexpr mod_int operator*(mod_int other) const { return mod_int(*this) *= other; }
    constexpr mod_int operator/(mod_int other) const { return mod_int(*this) /= other; }

    constexpr typename std::enable_if<IsPrime, mod_int>::type inverse() const {
        ll a = n, b = Mod, u = 1, v = 0;
        while(b) {
            ll t = a / b;
            a -= t * b; std::swap(a, b);
            u -= t * v; std::swap(u, v);
        }
        return mod_int(u);
    }

private:
    ll n;
};

template <int Mod, bool IsPrime>
std::ostream& operator<<(std::ostream& os, mod_int<Mod, IsPrime> const& n) {
    os << (int)n;
    return os;
}

constexpr int default_mod = 1000000007;

template <int Mod = default_mod>
mod_int<Mod, true> fact(int n, bool inv) {
    static std::vector<mod_int<Mod, true>> v = {1};
    static std::vector<mod_int<Mod, true>> v2 = {1};
    if(n >= static_cast<int>(v.size())) {
        const int from = v.size(), to = n + 1024;
        v.reserve(to); v2.reserve(to);
        for(int i = from; i < to; ++i) {
            v.push_back(v.back() * mod_int<Mod, true>(i));
            v2.push_back(v2.back() / mod_int<Mod, true>(i));
        }
    }
    return (inv ? v2[n] : v[n]);
}

template <int Mod = default_mod>
mod_int<Mod, true> comb(int n, int r) { // nCr
    if(r < 0 || r > n) return 0;
    return fact<Mod>(n, false) * fact<Mod>(r, true) * fact<Mod>(n - r, true);
}

using mint = mod_int<default_mod, true>; // default

template <int Mod, int PrimitiveRoot>
class NTT {
public:
    // assertion: v.size() == 2 ^ m
    static std::vector<int> fft(std::vector<int> v, bool inv) {
        for(auto& x : v) x %= Mod;
        const int n = v.size();
        assert((n ^ (n & -n)) == 0);
        int ww = mod_pow(PrimitiveRoot, (Mod - 1) / n, Mod);
        if(inv) ww = mod_inv(ww, Mod);
        for(int m = n; m >= 2; m >>= 1) {
            const int mh = m >> 1;
            int w = 1;
            for(int i = 0; i < mh; ++i) {
                for(int j = i; j < n; j += m) {
                    const int k = j + mh;
                    int x = v[j] - v[k];
                    if(x < 0) x += Mod;
                    v[j] += - Mod + v[k];
                    if(v[j] < 0) v[j] += Mod;
                    v[k] = (1LL * w * x) % Mod;
                }
                w = (1LL * w * ww) % Mod;
            }
            ww = (1LL * ww * ww) % Mod;
        }

        int i = 0;
        for(int j = 1; j < n - 1; ++j) {
            for(int k = n >> 1; k > (i ^= k); k >>= 1);
            if(j < i) swap(v[i], v[j]);
        }
        if(inv) {
            const int inv_n = mod_inv(n, Mod);
            for(auto& x : v) {
                x = (1LL * x * inv_n) % Mod;
            }
        }
        return v;
    }
    static std::vector<int> convolution(std::vector<int> f, std::vector<int> g) {
        int sz = 1;
        const int m = f.size() + g.size() - 1;
        while(sz < m) sz *= 2;
        f.resize(sz), g.resize(sz);
        f = NTT::fft(std::move(f), false); g = NTT::fft(std::move(g), false);
        for(int i = 0; i < sz; ++i) {
            f[i] = (1LL * f[i] * g[i]) % Mod;
        }

        return NTT::fft(std::move(f), true);
    }

    static int get_mod() {
        return Mod;
    }
};

using NTT_1 = NTT<167772161, 3>;  // 5 * 2^25 + 1
using NTT_2 = NTT<469762049, 3>;  // 7 * 2^26 + 1
using NTT_3 = NTT<1224736769, 3>; // 73 * 2^24 + 1

void shrink(vector<int>& v) {
    if(!v.empty() && v.back() == 1) v.pop_back();
}

std::vector<int> mod_convolution(std::vector<int> f, std::vector<int> g, const int mod) {
    for(auto& x : f) x %= mod;
    for(auto& y : g) y %= mod;
    const auto v1 = NTT_1::convolution(f, g);
    const auto v2 = NTT_2::convolution(f, g);
    const auto v3 = NTT_3::convolution(f, g);

    vector<int> res(v1.size());
    vector<ll> m = {NTT_1::get_mod(), NTT_2::get_mod(), NTT_3::get_mod()};
    for(int i = 0; i < (int)v1.size(); ++i) {
        vector<ll> u = {v1[i], v2[i], v3[i]};
        res[i] = garner(m, u, mod);
    }
    shrink(res);

    return res;
}

constexpr int mod = 1e9 + 7;

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0);
    int n, b; cin >> n >> b;
    vector<int> c(n + 1);
    for(int i = 0; i < n; ++i) {
        int s; cin >> s;
        c[s] += 1;
    }
    auto v = c;
    for(int i = n - 1; i >= 0; --i) {
        v[i] += v[i + 1];
    }
    queue<vector<int>> que;
    for(int i = 0; i < n; ++i) {
        if(c[n - i - 1] == 0) continue;
        const auto a = fact(v[n - i - 1], false) * fact(v[n - i], true) * mint(c[n - i - 1]) / mint(v[n - i - 1]);
        const auto b_ = fact(v[n - i - 1], false) * fact(v[n - i], true) * mint(v[n - i]) / mint(v[n - i - 1]);
        que.push({(int)b_, (int)a});
    }
    while(que.size() > 1) {
        auto f = que.front();
        que.pop();
        auto g = que.front();
        que.pop();
        auto h = mod_convolution(move(f), move(g), mod);
        shrink(h);
        que.push(move(h));
    }

    auto f = que.front();
    mint ans = 0, base = 1;
    for(int i = 0; i <= n; ++i, base *= b) {
        ans += mint(i) * base * ((int)f.size() > i ? mint(f[i]) : mint(0));
    }
    cout << ans << endl;
}
0