結果
問題 | No.599 回文かい |
ユーザー | stoq |
提出日時 | 2021-10-26 06:55:41 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 884 ms / 4,000 ms |
コード長 | 2,913 bytes |
コンパイル時間 | 2,608 ms |
コンパイル使用メモリ | 220,460 KB |
実行使用メモリ | 6,820 KB |
最終ジャッジ日時 | 2024-10-04 14:58:16 |
合計ジャッジ時間 | 5,742 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,816 KB |
testcase_01 | AC | 2 ms
6,820 KB |
testcase_02 | AC | 1 ms
6,816 KB |
testcase_03 | AC | 2 ms
6,816 KB |
testcase_04 | AC | 2 ms
6,816 KB |
testcase_05 | AC | 2 ms
6,820 KB |
testcase_06 | AC | 1 ms
6,820 KB |
testcase_07 | AC | 2 ms
6,816 KB |
testcase_08 | AC | 2 ms
6,816 KB |
testcase_09 | AC | 1 ms
6,816 KB |
testcase_10 | AC | 5 ms
6,820 KB |
testcase_11 | AC | 5 ms
6,816 KB |
testcase_12 | AC | 8 ms
6,816 KB |
testcase_13 | AC | 10 ms
6,816 KB |
testcase_14 | AC | 641 ms
6,816 KB |
testcase_15 | AC | 40 ms
6,816 KB |
testcase_16 | AC | 787 ms
6,820 KB |
testcase_17 | AC | 884 ms
6,820 KB |
testcase_18 | AC | 2 ms
6,816 KB |
testcase_19 | AC | 2 ms
6,816 KB |
testcase_20 | AC | 2 ms
6,820 KB |
evil_0.txt | AC | 261 ms
6,820 KB |
ソースコード
#include <bits/stdc++.h> #include <atcoder/fenwicktree> #include <atcoder/modint> using namespace std; using namespace atcoder; #pragma GCC target("avx2") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") using M1 = modint1000000007; using M2 = modint998244353; using hash_t = pair<M1, M2>; namespace atcoder { bool operator<(const M1 &t1, const M1 &t2) { return t1.val() < t2.val(); } bool operator<(const M2 &t1, const M2 &t2) { return t1.val() < t2.val(); } } // namespace atcoder struct Hash { int n; string s; long long B; bool calc_rev; fenwick_tree<M1> bit1, bit1_rev; fenwick_tree<M2> bit2, bit2_rev; vector<M1> Bp1, Bp1_inv; vector<M2> Bp2, Bp2_inv; Hash() {} Hash(string &s, bool calc_rev = true) : s(s), n(s.length()), calc_rev(calc_rev), Bp1(n + 1), Bp2(n + 1) { Bp1_inv.resize(n + 1), Bp2_inv.resize(n + 1); random_device seed; mt19937 engine(seed()); B = (long long)(engine()) + 1000; bit1 = fenwick_tree<M1>(n); bit2 = fenwick_tree<M2>(n); M1 p1 = 1; M2 p2 = 1; Bp1[0] = Bp1_inv[0] = 1, Bp2[0] = Bp2_inv[0] = 1; for (int i = 0; i < n; i++) { bit1.add(i, p1 * s[i]); bit2.add(i, p2 * s[i]); p1 *= B, p2 *= B; Bp1[i + 1] = p1; Bp2[i + 1] = p2; Bp1_inv[i + 1] = p1.inv(); Bp2_inv[i + 1] = p2.inv(); } if (not calc_rev) return; bit1_rev = fenwick_tree<M1>(n); bit2_rev = fenwick_tree<M2>(n); for (int i = 0; i < n; i++) { bit1_rev.add(i, Bp1[n - i - 1] * s[i]); bit2_rev.add(i, Bp2[n - i - 1] * s[i]); } } void update(int i, char c) { bit1.add(i, Bp1[i] * c - bit1.sum(i, i + 1)); bit2.add(i, Bp2[i] * c - bit2.sum(i, i + 1)); if (not calc_rev) return; bit1_rev.add(i, Bp1[n - i - 1] * c - bit1_rev.sum(i, i + 1)); bit2_rev.add(i, Bp2[n - i - 1] * c - bit2_rev.sum(i, i + 1)); } hash_t query(int l, int r, bool rev = false) { assert(l <= r); if (rev) { assert(calc_rev); hash_t res = {bit1_rev.sum(l, r), bit2_rev.sum(l, r)}; res.first *= Bp1_inv[n - r]; res.second *= Bp2_inv[n - r]; return res; } hash_t res = {bit1.sum(l, r), bit2.sum(l, r)}; res.first *= Bp1_inv[l]; res.second *= Bp2_inv[l]; return res; } bool is_palindrome(int l, int r) { assert(calc_rev); return query(l, (l + r) / 2, false) == query((l + r + 1) / 2, r, true); } }; int main() { string s; cin >> s; int n = s.length(); Hash hash(s, false); using mint = M1; vector<mint> dp(n); vector<int> used(n); auto f = [&](auto self, int l, int r) -> mint { if (used[l]) return dp[l]; mint res = 1; for (int l2 = l + 1, r2 = r - 1; l2 <= r2; l2++, r2--) { if (hash.query(l, l2) == hash.query(r2, r)) { res += self(self, l2, r2); } } used[l] = true; return dp[l] = res; }; cout << f(f, 0, n).val() << "\n"; }