Submission #25235163


Source Code Expand

// #define _GLIBCXX_DEBUG // for STL debug (optional)
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <cfloat>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <fstream>
#include <functional>
#include <bitset>
using namespace std;
using ll = long long int;
using int64 = long long int;
 
template<typename T> void chmax(T &a, T b) {a = max(a, b);}
template<typename T> void chmin(T &a, T b) {a = min(a, b);}
template<typename T> void chadd(T &a, T b) {a = a + b;}
 
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const int INF = 1LL << 29;
const ll LONGINF = 1LL << 60;
const ll MOD = 998244353LL;

// NTT (剰余環を用いた FFT)
// 任意 mod でやるなら、garner のアルゴリズム + ライブラリ下部が必須
// mod 998244353 なら NTT<998244353, 5> ntt; とかで十分です

template<ll mod, ll primitive_root>
struct NTT {
    int get_mod() const { return mod; }
    static const int P = 22;
    ll zs[P+1], zinvs[P+1];

    ll mod_pow(ll n, ll k) const {
        ll res = 1;
        for(; k>0; k>>=1) {
            if(k & 1) (res *= n) %= mod;
            (n *= n) %= mod;
        }
        return res;
    }
    
    NTT() {
        zs[P] = mod_pow(primitive_root, (mod - 1) >> P);
        zinvs[P] = mod_pow(zs[P], mod - 2);
        for(int k=P-1; k>=1; k--) {
            zs[k] = zs[k+1] * zs[k+1] % mod;
            zinvs[k] = zinvs[k+1] * zinvs[k+1] % mod;
        }
    }

    void dft(vector<ll> &A, int K, int sgn = 1) {
        int N = 1 << K;
        for(int i=0, j=1; j<N-1; j++) {
            for(int k=N >> 1; k>(i ^= k); k >>= 1);
            if(j < i) swap(A[i], A[j]);
        }
        
        for(int m=2, k=1; m<=N; m <<= 1, k++) {
            ll zeta = (sgn < 0 ? zinvs[k] : zs[k]);
            for(int i=0; i<N; i+=m) {
                ll zeta_pow = 1LL;
                for(int u=i, v=i+(m>>1); v<i+m; u++, v++) {
                    ll vl = A[u];
                    ll vr = zeta_pow * A[v] % mod;
                    A[u] = vl + vr;
                    A[v] = vl - vr + mod;
                    if(A[u] >= mod) A[u] -= mod;
                    if(A[v] >= mod) A[v] -= mod;
                    (zeta_pow *= zeta) %= mod;
                }
            }
        }
    }

    vector<ll> multiply(const vector<ll> &x, const vector<ll> &y) {
        if(x == y) return multiply(x);
        int sz = x.size() + y.size() - 1;
        int N = 1, K = 0; while(N < sz) N <<= 1, K++;
        ll inv_N = mod_pow(N, mod-2);

        vector<ll> X(N), Y(N);
        for(size_t i=0; i<x.size(); i++) X[i] = x[i];
        for(size_t i=0; i<y.size(); i++) Y[i] = y[i];
        dft(X, K), dft(Y, K);
        
        for(int i=0; i<N; i++) (X[i] *= Y[i]) %= mod;
        dft(X, K, -1);

        for(int i=0; i<sz; i++) (X[i] *= inv_N) %= mod;
        X.resize(sz);
        return X;
    }

    vector<ll> multiply(const vector<ll> &x) {
        int sz = x.size() + x.size() - 1;
        int N = 1, K = 0; while(N < sz) N <<= 1, K++;
        ll inv_N = mod_pow(N, mod-2);

        vector<ll> X(N);
        for(size_t i=0; i<x.size(); i++) X[i] = x[i];
        dft(X, K);

        for(int i=0; i<N; i++) (X[i] *= X[i]) %= mod;
        dft(X, K, -1);

        for(int i=0; i<sz; i++) (X[i] *= inv_N) %= mod;
        X.resize(sz);
        return X;
    }
};



// ModInt begin

using ll = long long;
template<ll mod>
struct ModInt {
    ll v;
    ll mod_pow(ll x, ll n) const {
        return (!n) ? 1 : (mod_pow((x*x)%mod,n/2) * ((n&1)?x:1)) % mod;
    }
    ModInt(ll a = 0) : v((a %= mod) < 0 ? a + mod : a) {}
    ModInt operator+ ( const ModInt& b ) const {
        return (v + b.v >= mod ? ModInt(v + b.v - mod) : ModInt(v + b.v));
    }
    ModInt operator- () const {
        return ModInt(-v);
    }
    ModInt operator- ( const ModInt& b ) const {
        return (v - b.v < 0 ? ModInt(v - b.v + mod) : ModInt(v - b.v));
    }
    ModInt operator* ( const ModInt& b ) const {return (v * b.v) % mod;}
    ModInt operator/ ( const ModInt& b ) const {return (v * mod_pow(b.v, mod-2)) % mod;}
    
    bool operator== ( const ModInt &b ) const {return v == b.v;}
    bool operator!= ( const ModInt &b ) const {return !(*this == b); }
    ModInt& operator+= ( const ModInt &b ) {
        v += b.v;
        if(v >= mod) v -= mod;
        return *this;
    }
    ModInt& operator-= ( const ModInt &b ) {
        v -= b.v;
        if(v < 0) v += mod;
        return *this;
    }
    ModInt& operator*= ( const ModInt &b ) {
        (v *= b.v) %= mod;
        return *this;
    }
    ModInt& operator/= ( const ModInt &b ) {
        (v *= mod_pow(b.v, mod-2)) %= mod;
        return *this;
    }
    ModInt pow(ll x) { return ModInt(mod_pow(v, x)); }
    // operator int() const { return int(v); }
    // operator long long int() const { return v; }
};

template<ll mod>
ModInt<mod> pow(ModInt<mod> n, ll k) {
    return ModInt<mod>(n.mod_pow(n.v, k));
}

template<ll mod>
ostream& operator<< (ostream& out, ModInt<mod> a) {return out << a.v;}
template<ll mod>
istream& operator>> (istream& in, ModInt<mod>& a) {
    in >> a.v;
    return in;
}

// ModInt end
using mint = ModInt<998244353>;

// 各種組み合わせを求めるライブラリ
template <typename NumType>
struct Combination {
    int LIMIT;
    vector<NumType> fact_, finv_;

    Combination() {}
    Combination(int LIMIT_) : LIMIT(LIMIT_), fact_(LIMIT+1), finv_(LIMIT+1) {
        fact_[0] = finv_[LIMIT] = NumType(1);
        for(int i=1; i<=LIMIT; i++) {
            fact_[i] = fact_[i-1] * NumType(i);
        }
        
        finv_[LIMIT] /= fact_[LIMIT];
        for(int i=LIMIT-1; i>=0; i--) {
            finv_[i] = finv_[i+1] * NumType(i+1);
        }
    }

    inline NumType fact(int k) const { return fact_[k]; }
    inline NumType finv(int k) const { return finv_[k]; }
    NumType P(int n, int r) const {
        if(r < 0 or n < r) return NumType(0);
        return fact_[n] * finv_[n-r];
    }
    NumType C(int n, int r) const {
        if(r < 0 or n < r) return NumType(0);
        return fact_[n] * finv_[n-r] * finv_[r];
    }
    // 重複組み合わせ
    NumType H(int n, int r) const {
        if(n < 0 or r < 0) return NumType(0);
        return r == 0 ? NumType(1) : C(n + r - 1, r);
    }
    // ベル数 (区別できる n 個のボールを区別できない k 個以下の箱に分割)
    // B(n, n) := n 個のボールを任意個のグループに分割する場合の数
    NumType B(int n, int k) const {
        if(n == 0) return NumType(1);
        k = min(n, k);
        NumType ret(0);
        vector<NumType> pref(k + 1); pref[0] = NumType(1);
        for(int i=1; i<=k; i++) {
            if(i & 1) pref[i] = pref[i-1] - finv_[i];
            else pref[i] = pref[i-1] + finv_[i];
        }
        for(int i=1; i<=k; i++) {
            // 累乗が必要なので適宜書き換える?
            // ModInt 使うならこれでいい
            ret += NumType(i).pow(n) * finv_[i] * pref[k-i];
        }
        return ret;
    }
    // スターリング数 (区別できる n 個のボールを区別できない k 個の箱に分割)
    NumType S(int n, int k) const {
        if(n < k) return NumType(0);
        NumType ans(0);
        for(int i=0; i<=k; i++) {
            NumType val = C(k, i) * NumType(i).pow(n);
            if((k - i) % 2) ans -= val;
            else ans += val;
        }
        return ans * finv_[k];
    }

    // ランダムウォーク: 左に X 回、右に Y 回進むとき、
    // 移動途中・終了時に座標 K を超えないものを数える
    // K が非負なら左側、負なら右側領域 (?) のランダムウォーク
    NumType walk(int X, int Y, int K) {
        if(K < 0) return walk(Y, X, -K);
        if(Y <= K) return C(X+Y, X); // 引っかからない
        if(Y - X > K) return NumType(0); // そもそも合計が超える
        
        int A = Y - K - 1, B = X + K + 1;
        return C(X+Y, X) - C(A+B, A);
    }
};

// P(n, k) := n の k 分割 (k 個の 0 以上の整数の和)
template <typename NumType, int LIMIT = 3010>
struct Partition {
    vector< vector<NumType> > dp;
    Partition() : dp(LIMIT, vector<NumType>(LIMIT)) {
        for(int k=0; k<LIMIT; k++) dp[0][k] = NumType(1);
        for(int i=1; i<LIMIT; i++) {
            for(int j=1; j<LIMIT; j++) {
                dp[i][j] += dp[i][j-1];
                if(i-j >= 0) dp[i][j] += dp[i-j][j];
            }
        }
    }
    inline NumType get(int n, int k) {
        if(n < 0 or k < 0) return NumType(0);
        return dp[n][k];
    }
};

int main() {
    int N; scanf("%d", &N);
    map<int, int> mp;
    for(int i=0; i<N; i++) {
        int v; cin >> v;
        mp[v]++;
    }

    Combination<mint> comb(200010);
    using Tp = tuple<int, vector<ll>, vector<ll>>;
    priority_queue<Tp, vector<Tp>, greater<Tp>> que;
    for(auto e : mp) {
        int sz = e.second;
        vector<ll> num(sz + 1), sum(sz + 1);
        for(int i=0; i<=sz; i++) {
            num[i] = comb.C(sz, i).v;
            sum[i] = (i > 0) * num[i];
        }
        que.emplace(sz, num, sum);
    }

    NTT<998244353, 3> ntt;
    while(que.size() >= 2) {
        auto [sz1, num1, sum1] = que.top(); que.pop();
        auto [sz2, num2, sum2] = que.top(); que.pop();
        vector<ll> n_c = ntt.multiply(num1, num2);
        vector<ll> n_s1 = ntt.multiply(sum1, num2);
        vector<ll> n_s2 = ntt.multiply(sum2, num1);

        vector<ll> n_s(n_c.size());
        for(size_t i=0; i<n_s.size(); i++) {
            (n_s[i] += n_s1[i] + n_s2[i]) %= MOD;
        }
        que.emplace(sz1 + sz2, n_c, n_s);
    }

    vector<ll> sum = get<2>(que.top());
    for(int i=1; i<=N; i++) {
        mint all = comb.C(N, i);
        mint ans = mint(sum[i]) / all;
        cout << ans << endl;
    }
    return 0;
}

Submission Info

Submission Time
Task G - Colorful Candies 2
User tsutaj
Language C++ (GCC 9.2.1)
Score 600
Code Size 10425 Byte
Status AC
Exec Time 863 ms
Memory 17720 KiB

Compile Error

./Main.cpp: In function ‘int main()’:
./Main.cpp:292:17: warning: ignoring return value of ‘int scanf(const char*, ...)’, declared with attribute warn_unused_result [-Wunused-result]
  292 |     int N; scanf("%d", &N);
      |            ~~~~~^~~~~~~~~~

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 600 / 600
Status
AC × 2
AC × 43
Set Name Test Cases
Sample example0.txt, example1.txt
All 000.txt, 001.txt, 002.txt, 003.txt, 004.txt, 005.txt, 006.txt, 007.txt, 008.txt, 009.txt, 010.txt, 011.txt, 012.txt, 013.txt, 014.txt, 015.txt, 016.txt, 017.txt, 018.txt, 019.txt, 020.txt, 021.txt, 022.txt, 023.txt, 024.txt, 025.txt, 026.txt, 027.txt, 028.txt, 029.txt, 030.txt, 031.txt, 032.txt, 033.txt, 034.txt, 035.txt, 036.txt, 037.txt, 038.txt, 039.txt, 040.txt, example0.txt, example1.txt
Case Name Status Exec Time Memory
000.txt AC 122 ms 8012 KiB
001.txt AC 113 ms 7840 KiB
002.txt AC 9 ms 6440 KiB
003.txt AC 860 ms 17720 KiB
004.txt AC 863 ms 17668 KiB
005.txt AC 840 ms 15456 KiB
006.txt AC 839 ms 15360 KiB
007.txt AC 708 ms 14380 KiB
008.txt AC 707 ms 14284 KiB
009.txt AC 721 ms 13700 KiB
010.txt AC 735 ms 13588 KiB
011.txt AC 645 ms 11116 KiB
012.txt AC 518 ms 10224 KiB
013.txt AC 393 ms 10396 KiB
014.txt AC 273 ms 10244 KiB
015.txt AC 587 ms 10768 KiB
016.txt AC 584 ms 10992 KiB
017.txt AC 587 ms 11180 KiB
018.txt AC 585 ms 10940 KiB
019.txt AC 584 ms 10888 KiB
020.txt AC 682 ms 11940 KiB
021.txt AC 613 ms 10944 KiB
022.txt AC 484 ms 10316 KiB
023.txt AC 326 ms 10048 KiB
024.txt AC 111 ms 8092 KiB
025.txt AC 182 ms 9912 KiB
026.txt AC 183 ms 10300 KiB
027.txt AC 185 ms 9984 KiB
028.txt AC 271 ms 9804 KiB
029.txt AC 269 ms 10236 KiB
030.txt AC 265 ms 9816 KiB
031.txt AC 258 ms 9876 KiB
032.txt AC 327 ms 10312 KiB
033.txt AC 565 ms 12048 KiB
034.txt AC 485 ms 11204 KiB
035.txt AC 98 ms 7656 KiB
036.txt AC 101 ms 7428 KiB
037.txt AC 345 ms 9700 KiB
038.txt AC 80 ms 7300 KiB
039.txt AC 622 ms 11860 KiB
040.txt AC 90 ms 7120 KiB
example0.txt AC 8 ms 6268 KiB
example1.txt AC 8 ms 6440 KiB