#include <bits/stdc++.h> using namespace std; const int N = 2; int mod[N], seed[N], inv_seed[N]; int power(int a, int n, int mod) { int r = 1; while (n > 0) { if (n % 2) { r = (1LL * r * a) % mod; } a = (1LL * a * a) % mod; n /= 2; } return r; } bool isPrime(int n) { if (n == 1) return false; for (int i = 2; i * i <= n; ++i) if (n % i == 0) return false; return true; } void prepare() { const int BOUND_MOD = 500 * 1000 * 1000; const int BOUND_SEED = 100; for (int i = 0; i < N; ++i) { mod[i] = BOUND_MOD + rand() % BOUND_MOD; seed[i] = BOUND_SEED + rand() % BOUND_SEED; while (!isPrime(mod[i])) ++mod[i]; inv_seed[i] = power(seed[i], mod[i] - 2, mod[i]); } } void solve() { const int BOUND_LEN = 20 * 1000 * 1000 + 5; int hash[N], rev_hash[N], pw[N], rev_pw[N]; fill(hash, hash + N, 0); fill(rev_hash, rev_hash + N, 0); fill(pw, pw + N, 1); for (int i = 0; i < N; ++i) { rev_pw[i] = power(seed[i], BOUND_LEN, mod[i]); } int n; if (scanf("%d\n", &n)) { char c; int len = 0; while (true) { c = getchar(); if (c == '\n' || c == EOF) break; for (int i = 0; i < N; ++i) { hash[i] = (hash[i] + 1LL * pw[i] * c) % mod[i]; rev_hash[i] = (rev_hash[i] + 1LL * rev_pw[i] * c) % mod[i]; pw[i] = (1LL * pw[i] * seed[i]) % mod[i]; rev_pw[i] = (1LL * rev_pw[i] * inv_seed[i]) % mod[i]; } ++len; } bool failed = false; for (int i = 0; i < N; ++i) { rev_hash[i] = (1LL * rev_hash[i] * power(inv_seed[i], BOUND_LEN - len + 1, mod[i])) % mod[i]; if (hash[i] != rev_hash[i]) { failed = true; break; } } if (!failed) { cout << "TAK\n"; } else { cout << "NIE\n"; } } } int main() { srand(44747); prepare(); solve(); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | #include <bits/stdc++.h> using namespace std; const int N = 2; int mod[N], seed[N], inv_seed[N]; int power(int a, int n, int mod) { int r = 1; while (n > 0) { if (n % 2) { r = (1LL * r * a) % mod; } a = (1LL * a * a) % mod; n /= 2; } return r; } bool isPrime(int n) { if (n == 1) return false; for (int i = 2; i * i <= n; ++i) if (n % i == 0) return false; return true; } void prepare() { const int BOUND_MOD = 500 * 1000 * 1000; const int BOUND_SEED = 100; for (int i = 0; i < N; ++i) { mod[i] = BOUND_MOD + rand() % BOUND_MOD; seed[i] = BOUND_SEED + rand() % BOUND_SEED; while (!isPrime(mod[i])) ++mod[i]; inv_seed[i] = power(seed[i], mod[i] - 2, mod[i]); } } void solve() { const int BOUND_LEN = 20 * 1000 * 1000 + 5; int hash[N], rev_hash[N], pw[N], rev_pw[N]; fill(hash, hash + N, 0); fill(rev_hash, rev_hash + N, 0); fill(pw, pw + N, 1); for (int i = 0; i < N; ++i) { rev_pw[i] = power(seed[i], BOUND_LEN, mod[i]); } int n; if (scanf("%d\n", &n)) { char c; int len = 0; while (true) { c = getchar(); if (c == '\n' || c == EOF) break; for (int i = 0; i < N; ++i) { hash[i] = (hash[i] + 1LL * pw[i] * c) % mod[i]; rev_hash[i] = (rev_hash[i] + 1LL * rev_pw[i] * c) % mod[i]; pw[i] = (1LL * pw[i] * seed[i]) % mod[i]; rev_pw[i] = (1LL * rev_pw[i] * inv_seed[i]) % mod[i]; } ++len; } bool failed = false; for (int i = 0; i < N; ++i) { rev_hash[i] = (1LL * rev_hash[i] * power(inv_seed[i], BOUND_LEN - len + 1, mod[i])) % mod[i]; if (hash[i] != rev_hash[i]) { failed = true; break; } } if (!failed) { cout << "TAK\n"; } else { cout << "NIE\n"; } } } int main() { srand(44747); prepare(); solve(); } |