結果
問題 | No.3014 多項式ハッシュに関する教育的な問題 |
ユーザー | anta |
提出日時 | 2015-10-20 03:01:53 |
言語 | C++11 (gcc 11.4.0) |
結果 |
AC
|
実行時間 | 12 ms / 5,000 ms |
コード長 | 2,407 bytes |
コンパイル時間 | 1,014 ms |
コンパイル使用メモリ | 87,424 KB |
実行使用メモリ | 5,248 KB |
最終ジャッジ日時 | 2024-07-22 10:59:27 |
合計ジャッジ時間 | 1,459 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
ソースコード
#include <vector> #include <valarray> #include <cassert> #include <cmath> #include <iostream> #include <string> using namespace std; typedef long double R; typedef valarray<R> VecR; typedef vector<VecR> MatR; inline R dot(const VecR &x, const VecR &y) { return (x * y).sum(); } inline R norm(const VecR &x) { return dot(x, x); } void computeGSO(const MatR &g, MatR &r, MatR &u) { int n = g.size(); for(int i = 0; i < n; ++ i) { for(int j = 0; j < i; ++ j) u[i][j] = dot(g[i], r[j]) / norm(r[j]); r[i] = g[i]; for(int j = 0; j < i; ++ j) r[i] -= u[i][j] * r[j]; } } void basisReduction(vector<vector<long long> > &f) { int n = f.size(); MatR g(n), r(n), u(n); for(int i = 0; i < n; ++ i) { assert(f[i].size() == n); g[i].resize(n); for(int j = 0; j < n; ++ j) g[i][j] = (R)f[i][j]; r[i].resize(n); u[i].resize(i); } computeGSO(g, r, u); for(int i = 1; i < n; ) { for(int j = i-1; j >= 0; -- j) { if(abs(u[i][j]) < .5) continue; R c = floor(u[i][j] + .5); g[i] -= c * g[j]; long long cZ = (long long)c; for(int k = 0; k < n; ++ k) f[i][k] -= cZ * f[j][k]; computeGSO(g, r, u); } if(i > 0 && norm(r[i-1]) > norm(r[i]) * 2) { swap(g[i-1], g[i]); swap(f[i-1], f[i]); computeGSO(g, r, u); -- i; }else { ++ i; } } } long long calcHash(const string &S, long long P, long long B) { long long h = 0; for(int i = 0; i < (int)S.size(); ++ i) h = ((__int128)h * B + S[i]) % P; return h; } int main() { assert(sizeof(long double) >= 10); const int Alphas = 26; long long P, B; while(cin >> P >> B) { int n; vector<int> poly; for(n = 16;; n += 4) { vector<vector<long long> > L(n, vector<long long>(n, 0)); for(int i = 0; i < n - 1; ++ i) { L[i][i + 0] = -B; L[i][i + 1] = 1; } L[n - 1][0] = P; basisReduction(L); bool ok = true; for(int i = 0; i < n; ++ i) ok &= abs(L[0][i]) < Alphas; if(ok) { poly.resize(n); for(int i = 0; i < n; ++ i) poly[i] = (int)L[0][i]; break; } } int len = n; while(len > 1 && poly[len - 1] == 0) -- len; string S(len, '?'), T(len, '?'); for(int i = 0; i < len; ++ i) { int a = poly[len - 1 - i]; if(a >= 0) { S[i] = 'a' + a; T[i] = 'a'; } else { S[i] = 'a'; T[i] = 'a' - a; } } assert(calcHash(S, P, B) == calcHash(T, P, B)); cout << S << endl; cout << T << endl; } return 0; }