結果
| 問題 |
No.2720 Sum of Subarray of Subsequence of...
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-01-26 04:07:25 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 372 ms / 4,000 ms |
| コード長 | 2,298 bytes |
| コンパイル時間 | 5,005 ms |
| コンパイル使用メモリ | 266,312 KB |
| 最終ジャッジ日時 | 2025-02-18 22:43:08 |
|
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 31 |
ソースコード
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
#include <atcoder/all>
using namespace atcoder;
using mint = modint998244353;
int main() {
int n, m;
cin >> n >> m;
assert(1 <= n && n <= (int)1e5);
assert(1 <= m && m <= (int)1e5);
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
assert(0 <= a[i] && a[i] < 998244353);
}
string s;
cin >> s;
for (int j = 0; j < m; j++) {
assert(s[j] == 'a' || s[j] == 's');
}
// g_j(x) を (1-x)^(e_1) (1-2x)^(e_2) (1-3x)^(e_3) ... と表したときの指数列を更新していく.
deque<int> q{ -1 }; int q_sum = -1;
for(auto c : s) {
if (c == 's') {
q.push_front(-q_sum - 1);
q_sum = -1;
}
else if (c == 'a') {
q.front()--;
q_sum--;
}
}
q.push_front(0);
int K = (int)q.size();
// g_M(x) の (1-kx) たちを分子と分母に振り分ける.
vector<vector<mint>> nums{ {1} }, dnms{ {1} };
for (int k = 1; k < K; k++) {
if (q[k] > 0) {
for (int tmp = 0; tmp < q[k]; tmp++) {
nums.push_back(vector<mint>{1, -k});
}
}
else if (q[k] < 0) {
for (int tmp = 0; tmp < -q[k]; tmp++) {
dnms.push_back(vector<mint>{1, -k});
}
}
}
// 分子を分割統治法で求める.
int Dnum = (int)nums.size();
for (int d = 1; d < Dnum; d *= 2) {
for (int i = 0; i + d < Dnum; i += 2 * d) {
nums[i] = convolution(nums[i], nums[i + d]);
}
}
// 分母を分割統治法で求める.
int Ddnm = (int)dnms.size();
for (int d = 1; d < Ddnm; d *= 2) {
for (int i = 0; i + d < Ddnm; i += 2 * d) {
dnms[i] = convolution(dnms[i], dnms[i + d]);
}
}
// 分母の形式的冪級数としての逆元を求める.
dnms[0].resize(n);
vector<mint> dnm_inv{ dnms[0][0].inv() };
for (int k = 1; k < n; k *= 2) {
int len = min(2 * k, n);
vector<mint> tmp(len);
int i_ub = min(len, n);
for (int i = 0; i < i_ub; i++) tmp[i] = -dnms[0][i];
tmp = convolution(tmp, dnm_inv);
tmp.resize(len);
tmp[0] += 2;
dnm_inv = convolution(dnm_inv, tmp);
dnm_inv.resize(len);
}
// g_M(x) を求める.
auto f = convolution(nums[0], dnm_inv);
// 答えへの寄与を足し合わせる.
mint res;
for (int i = 0; i < n; i++) {
int l = i;
int r = n - 1 - i;
res += a[i] * f[l] * f[r];
}
cout << res.val() << endl;
}