#include using namespace std; #include using namespace atcoder; using mint = atcoder::modint998244353; // using mint = double; #define rep(i, l, r) for (int i = (int)(l); i<(int)(r); i++) #define ll long long #define ld long double #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() #define siz(x) (int)(x).size() template bool chmin(T& a, T b) { if (a > b) {a = b; return true;} return false; } template bool chmax(T& a, T b) { if (a < b) {a = b; return true;} return false; } const int inf = 1e9; const ll INF = 4e18; template using pq = priority_queue, less>; template using spq = priority_queue, greater>; vector di = {0, 0, 1, -1}; vector dj = {1, -1, 0, 0}; struct Edge { int to, cost; }; //窃盗元:https://nononmath.hatenablog.com/entry/2024/06/11/193707 mint bounded_increasing_sequence(const vector &A) { const int n = A.size(); const int m = A[n - 1]; // 階乗とその逆元の前計算 vector fac(n + m + 1), finv(n + m + 1); { fac[0] = 1; for (int i = 1; i <= n + m; i++) fac[i] = i * fac[i - 1]; finv[n + m] = fac[n + m].inv(); for (int i = n + m; i >= 1; i--) finv[i - 1] = i * finv[i]; } auto rec = [&](const auto &rec, int l, int r, int d, const vector &bottom_edge) -> vector { if (l + 1 == r) { return vector(A[l] - d, l == 0 ? mint::raw(1) : bottom_edge[0]); } int m = (l + r) / 2; int h = A[m] - d, w = r - m; // 左下の計算 auto left_edge = rec(rec, l, m, d, vector(bottom_edge.begin(), bottom_edge.begin() + m - l)); left_edge.resize(h); vector top_edge(w); // 左から上への寄与 if (h) { vector f(h), g(h + w); for (int i = 0; i < h; i++) f[i] = left_edge[i] * finv[h - 1 - i]; for (int i = 0; i < h + w; i++) g[i] = fac[i]; f = convolution(f, g); for (int i = 0; i < w; i++) top_edge[i] += finv[i] * f[h - 1 + i]; } // 下から上への寄与 if (h) { vector f(w), g(w); for (int i = 0; i < w; i++) f[i] = bottom_edge[i + m - l]; for (int i = 0; i < w; i++) g[i] = fac[h - 1 + i] * finv[i]; f = convolution(f, g); for (int i = 0; i < w; i++) top_edge[i] += finv[h - 1] * f[i]; } else { for (int i = 0; i < w; i++) top_edge[i] = bottom_edge[i + m - l]; } vector right_edge(A[r - 1] - d); // 左から右への寄与 if (h) { vector f(h), g(h + w); for (int i = 0; i < h; i++) f[i] = left_edge[i]; for (int i = 0; i < h + w; i++) g[i] = fac[w - 1 + i] * finv[i]; f = convolution(f, g); for (int i = 0; i < h; i++) right_edge[i] += finv[w - 1] * f[i]; } // 下から右への寄与 if (h) { vector f(w), g(h + w); for (int i = 0; i < w; i++) f[i] = bottom_edge[m - l + i] * finv[w - 1 - i]; for (int i = 0; i < h + w; i++) g[i] = fac[i]; f = convolution(f, g); for (int i = 0; i < h; i++) right_edge[i] += finv[i] * f[w - 1 + i]; } vector upper_right = rec(rec, m, r, A[m], top_edge); int k = upper_right.size(); // 右側の情報のマージ for (int i = 0; i < k; i++) right_edge[i + h] += upper_right[i]; return right_edge; }; vector right_edge = rec(rec, 0, n, 0, vector(n)); mint res = 0; for (mint x : right_edge) res += x; return res; } int main() { string S; cin >> S; //各iで+iすることにする int N = siz(S); vector P; rep(i, 0, N) { if (S[i] == 'A') P.push_back(i); } int M = siz(P); if (M == 0) { cout << 1 << endl; return 0; } vector A(M), B(M); //0 <= x[i] + i <= P[i] //0 <= x[i] <= P[i] - i rep(i, 0, M) { A[i] = P[i] - i + 1; } mint ans = bounded_increasing_sequence(A); cout << ans.val() << endl; }