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
2021-08-21 22:15:21+0900
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
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