結果
問題 | No.829 成長関数インフレ中 |
ユーザー | kazuma |
提出日時 | 2019-05-03 23:00:27 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
RE
|
実行時間 | - |
コード長 | 6,037 bytes |
コンパイル時間 | 2,850 ms |
コンパイル使用メモリ | 227,236 KB |
実行使用メモリ | 37,864 KB |
最終ジャッジ日時 | 2024-06-10 07:03:49 |
合計ジャッジ時間 | 7,480 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 26 ms
19,072 KB |
testcase_01 | AC | 27 ms
19,072 KB |
testcase_02 | AC | 26 ms
19,072 KB |
testcase_03 | AC | 25 ms
19,072 KB |
testcase_04 | RE | - |
testcase_05 | AC | 25 ms
19,200 KB |
testcase_06 | RE | - |
testcase_07 | AC | 26 ms
19,072 KB |
testcase_08 | AC | 24 ms
19,144 KB |
testcase_09 | AC | 24 ms
18,944 KB |
testcase_10 | AC | 26 ms
19,072 KB |
testcase_11 | AC | 25 ms
18,944 KB |
testcase_12 | AC | 54 ms
19,072 KB |
testcase_13 | AC | 27 ms
19,072 KB |
testcase_14 | AC | 46 ms
19,144 KB |
testcase_15 | RE | - |
testcase_16 | RE | - |
testcase_17 | RE | - |
testcase_18 | RE | - |
testcase_19 | RE | - |
testcase_20 | RE | - |
testcase_21 | AC | 42 ms
19,072 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; template<int MOD> struct mod_int { static const int mod = MOD; unsigned x; mod_int() : x(0) { } mod_int(int sig) { int sigt = sig % MOD; if (sigt < 0) sigt += MOD; x = sigt; } mod_int(long long sig) { int sigt = sig % MOD; if (sigt < 0) sigt += MOD; x = sigt; } int get() const { return (int)x; } mod_int &operator+=(mod_int that) { if ((x += that.x) >= MOD) x -= MOD; return *this; } mod_int &operator-=(mod_int that) { if ((x += MOD - that.x) >= MOD) x -= MOD; return *this; } mod_int &operator*=(mod_int that) { x = (unsigned long long)x * that.x % MOD; return *this; } mod_int &operator/=(mod_int that) { return *this *= that.inverse(); } mod_int operator+(mod_int that) const { return mod_int(*this) += that; } mod_int operator-(mod_int that) const { return mod_int(*this) -= that; } mod_int operator*(mod_int that) const { return mod_int(*this) *= that; } mod_int operator/(mod_int that) const { return mod_int(*this) /= that; } mod_int inverse() const { long long a = x, b = MOD, u = 1, v = 0; while (b) { long long t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v); } return mod_int(u); } }; template<int MOD> istream& operator >> (istream& is, mod_int<MOD>& val) { long long x; is >> x; val = x; return is; } template<int MOD> ostream& operator << (ostream& os, const mod_int<MOD>& val) { os << val.get(); return os; } const int mod = 1e9 + 7; using mint = mod_int<mod>; const int MAX = 2e6; bool inited = false; mint fac[MAX + 1]; mint rfac[MAX + 1]; void init() { inited = true; fac[0] = 1; for (int i = 1; i <= MAX; i++) { fac[i] = fac[i - 1] * i; } rfac[MAX] = fac[MAX].inverse(); for (int i = MAX; i >= 1; i--) { rfac[i - 1] = rfac[i] * i; } } mint nPr(int n, int r) { if (!inited) init(); return r < 0 || n < r ? 0 : fac[n] * rfac[n - r]; } mint nCr(int n, int r) { if (!inited) init(); return r < 0 || n < r ? 0 : fac[n] * rfac[n - r] * rfac[r]; } mint nHr(int n, int r) { if (!inited) init(); return r == 0 ? 1 : nCr(n + r - 1, r); } 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 garner(std::vector<ll> m, std::vector<ll> u, int md) { 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]) % md; } return res; } ll mod_pow(ll x, ll n, int md) { ll res = 1; while (n) { if (n & 1) (res *= x) %= md; (x *= x) %= md; n >>= 1; } return res; } template <int Mod, int PrimitiveRoot> class NTT { public: // assertion: v.size() == 2 ^ m static std::vector<int> fft(std::vector<int> v, bool inv) { 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; assert(0 <= x && x < 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 std::vector<int> mod_convolution(std::vector<int> f, std::vector<int> g, const int md) { for (auto& x : f) x %= md; for (auto& y : g) y %= md; 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, md); } return res; } vector<int> calc(int lb, int ub, const vector<vector<int>>& a) { if (ub - lb == 1) return a[lb]; int m = (lb + ub) / 2; auto v1 = calc(lb, m, a); auto v2 = calc(m, ub, a); auto v = mod_convolution(v1, v2, mod); while (!v.empty() && v.back() == 0) v.pop_back(); while (v.size() & (v.size() - 1)) v.push_back(0); return v; } int main() { init(); int N; mint B; cin >> N >> B; map<int, int> cnt; for (int i = 0; i < N; i++) { int S; cin >> S; cnt[S]++; } int size = N; vector<vector<int>> aa; for (auto p : cnt) { mint all = nCr(size, p.second) * fac[p.second]; mint x0 = nCr(size - 1, p.second) * fac[p.second]; vector<int> vec; vec.push_back(x0.get()); vec.push_back(((all - x0) * B).get()); aa.emplace_back(vec); size -= p.second; } auto v = calc(0, aa.size(), aa); mint res = 0; for (int i = 0; i < (int)v.size(); i++) { res += mint(v[i]) * i; } cout << res << endl; return 0; }