結果
| 問題 |
No.2633 Subsequence Combination Score
|
| コンテスト | |
| ユーザー |
👑 potato167
|
| 提出日時 | 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;
}
potato167