結果
問題 | No.8014 多項式ハッシュに関する教育的な問題 |
ユーザー |
![]() |
提出日時 | 2020-03-03 04:00:28 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 4 ms / 5,000 ms |
コード長 | 3,279 bytes |
コンパイル時間 | 1,120 ms |
コンパイル使用メモリ | 86,432 KB |
最終ジャッジ日時 | 2025-01-09 04:12:18 |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 1 |
コンパイルメッセージ
main.cpp: In function ‘int main()’: main.cpp:86:8: warning: ignoring return value of ‘int scanf(const char*, ...)’ declared with attribute ‘warn_unused_result’ [-Wunused-result] 86 | scanf("%jd %jd", &p, &b); | ~~~~~^~~~~~~~~~~~~~~~~~~
ソースコード
/*** @brief ユーザ定義リテラル* @author えびちゃん*/#ifndef H_int_literals#define H_int_literals#include <cstddef>#include <cstdint>constexpr intmax_t operator ""_jd(unsigned long long n) { return n; }constexpr uintmax_t operator ""_ju(unsigned long long n) { return n; }constexpr size_t operator ""_zu(unsigned long long n) { return n; }constexpr ptrdiff_t operator ""_td(unsigned long long n) { return n; }#endif /* !defined(H_int_literals) */#include <cstdio>#include <cstdint>#include <cassert>#include <algorithm>#include <queue>#include <string>#include <tuple>#include <utility>#include <vector>std::vector<int> tree_attack(intmax_t p, intmax_t b, size_t k) {struct node {intmax_t value;size_t pos, neg;node() = default;node(intmax_t v, size_t l, size_t r): value(v), pos(l), neg(r) {}bool operator <(node const& that) const { return value < that.value; }};std::vector<std::vector<node>> cl(k+1);size_t n = 1_zu << k;cl[0].assign(n, node(1, n-1, -1_zu));for (size_t j = 1; j < n; ++j) {cl[0][j].value = __int128(cl[0][j-1].value) * b % p;cl[0][j].pos = n-1-j;}std::sort(cl[0].begin(), cl[0].end());for (size_t i = 1; i <= k; ++i) {cl[i].resize(n >> i);for (size_t j = 0; j < cl[i].size(); ++j) {size_t jl = j << 1 | 0;size_t jr = j << 1 | 1;if (cl[i-1][jr] < cl[i-1][jl]) {cl[i][j].value = cl[i-1][jl].value - cl[i-1][jr].value;cl[i][j].pos = jl;cl[i][j].neg = jr;} else {cl[i][j].value = cl[i-1][jr].value - cl[i-1][jl].value;cl[i][j].pos = jr;cl[i][j].neg = jl;}}std::sort(cl[i].begin(), cl[i].end());if (cl[i][0].value > 0) continue;std::vector<int> res(n, 0);std::queue<std::tuple<size_t, size_t, bool>> q; // i, j, neg?q.emplace(i-1, cl[i][0].pos, false);q.emplace(i-1, cl[i][0].neg, true);while (!q.empty()) {auto [i, j, neg] = q.front();q.pop();if (i == -1_zu) {if (j != -1_zu) res[j] = (neg? -1: +1);continue;}q.emplace(i-1, cl[i][j].pos, neg);q.emplace(i-1, cl[i][j].neg, !neg);}return res;}return {};}int main() {intmax_t p, b;scanf("%jd %jd", &p, &b);auto h = [&](auto const& s) -> intmax_t {__int128 h = 0;for (size_t i = 0; i < s.size(); ++i)h = (h * b + s[i]) % p;return h;};size_t k = 2;std::string s, t;do {size_t n = 1_zu << k;std::vector<int> a = tree_attack(p, b, k);if (a.empty()) {++k;continue;}s = t = std::string(n, 'x');for (size_t i = 0; i < a.size(); ++i) {if (a[i] == +1) {s[i] = 'b';t[i] = 'a';}if (a[i] == -1) {s[i] = 'a';t[i] = 'b';}}} while (s.empty());printf("%s\n", s.data());printf("%s\n", t.data());std::vector<int> u(s.length());for (size_t i = 0; i < s.length(); ++i)u[i] = s[i]-t[i];fprintf(stderr, "length: %zu\n", s.length());fprintf(stderr, "h(s): %jd\n", h(s));fprintf(stderr, "h(t): %jd\n", h(t));fprintf(stderr, "h(s-t): %jd\n", h(u));assert(h(u) == 0);assert(h(s) == h(t));assert(s != t);}