結果
問題 |
No.2633 Subsequence Combination Score
|
ユーザー |
👑 ![]() |
提出日時 | 2025-04-17 11:22:26 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 3,216 bytes |
コンパイル時間 | 3,669 ms |
コンパイル使用メモリ | 239,760 KB |
実行使用メモリ | 25,700 KB |
最終ジャッジ日時 | 2025-04-17 11:22:36 |
合計ジャッジ時間 | 8,898 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | WA * 3 |
other | TLE * 1 -- * 37 |
ソースコード
#include <bits/stdc++.h> #include <atcoder/convolution> using namespace std; using ll = long long; const int MOD = 998244353; // fast power mod ll modpow(ll a, ll e=MOD-2){ ll r=1; while(e){ if(e&1) r=r*a%MOD; a=a*a%MOD; e>>=1; } return r; } // precompute factorials up to MAXA, and invfact static const int MAXA = 100000; ll fact[MAXA+1], invfact[MAXA+1]; inline ll C(int n,int k){ if(k<0 || k>n) return 0; return fact[n]*invfact[k]%MOD*invfact[n-k]%MOD; } vector<int> A; vector<ll> dp, tmp; // dp[x]: 現在までの累積 dp 値、tmp は CDQ用 // CDQ 区間 [l, r) で更新 void cdq(int l,int r){ if(r-l<=1) return; int m=(l+r)/2; // 左半分で再帰 cdq(l,m); // 左半分の dp 増分を使って右半分 tmp を更新 // we want for each j in [m,r) sum_{i in [l,m)} dp[i] * C(A[i], A[j]) over those A[i] >= A[j] // group by value v = A[j], gather all i's and j's // build f,g sequences of length MAXA+1: f[v] = sum dp[i] for i in [l,m) with A[i]=v // g[v] = C(v, k) for k = A[j] vector<ll> f(MAXA+1,0), g(MAXA+1,0); for(int i=l;i<m;i++) f[A[i]] = (f[A[i]] + dp[i])%MOD; // prefix sum on f: F[v] = sum_{u>=v} f[u] for(int v=MAXA-1;v>=0;v--) f[v]=(f[v]+f[v+1])%MOD; // build G[k][v]=C(v,k), but we only need for k = A[j] // instead: for fixed k we need G_k[v] = C(v,k) for v>=k else 0. // We will do convolution of F (length MAXA+1) and H where H[u]=C(u,k) for u<=MAXA. // But since k varies per j, we cannot do single convolution: instead we do for each distinct k group all j. // For simplicity, do naive inner for distinct k in [m,r): unordered_map<int, vector<int>> pos; for(int j=m;j<r;j++) pos[A[j]].push_back(j); for(auto &kv : pos){ int k = kv.first; auto &vec = kv.second; // build h[v]=C(v,k) for v=0..MAXA for(int v=0;v<=MAXA;v++){ g[v] = C(v,k); } // convolution of f and g auto conv = atcoder::convolution(f, g); // conv[v + u] contains sum f[u]*g[v], but we want for each j: sum_{v>=k} F[v]*C(v,k) // Actually, conv index i = u+v. We need for each j: // sum_{u>=0} F[u] * C(u,k) = conv[k] ll val = (k < (int)conv.size() ? conv[k] : 0); for(int j : vec){ tmp[j] = (tmp[j] + val) % MOD; } } // 右半分 dp に反映 for(int i=m;i<r;i++){ dp[i] = (dp[i] + tmp[i]) % MOD; } fill(tmp.begin()+m, tmp.begin()+r, 0); // 右半分再帰 cdq(m,r); } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; A.resize(N); for(int i=0;i<N;i++) cin >> A[i]; // 前処理 fact[0]=1; for(int i=1;i<=MAXA;i++) fact[i]=fact[i-1]*i%MOD; invfact[MAXA]=modpow(fact[MAXA]); for(int i=MAXA;i>0;i--) invfact[i-1]=invfact[i]*i%MOD; dp.assign(N, 0); tmp.assign(N, 0); // 初期状態:長さ1 の部分列それぞれ f=1 for(int i=0;i<N;i++) dp[i]=1; // CDQ 全体 cdq(0, N); // 答えは dp の総和 ll ans = 0; for(int i=0;i<N;i++) ans = (ans + dp[i]) % MOD; cout << ans << "\n"; return 0; }