제출 #1291051

#제출 시각아이디문제언어결과실행 시간메모리
1291051vk3601hOsmosmjerka (COCI17_osmosmjerka)C++20
100 / 160
684 ms18364 KiB
#include <bits/stdc++.h> using namespace std; long long rng(long long low, long long high){ static mt19937 gen(chrono::steady_clock::now().time_since_epoch().count()); return uniform_int_distribution<long long>(low, high)(gen); } const long long M = (1ll << 61) - 1; const long long B = rng((1ll << 20), (1ll << 40)); const int DX[8] = {-1, 1, 0, 0, -1, 1, -1, 1}; const int DY[8] = {0, 0, -1, 1, -1, -1, 1, 1}; long long mod_mul(long long a, long long b) {return (__int128)a * b % M;} int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); int row_num, col_num, len; cin >> row_num >> col_num >> len; int size = row_num * col_num; vector<string> grid(row_num); for (string &str : grid) cin >> str; vector<long long> pow(size + 1); pow[0] = 1; for (int i = 1; i <= size; i++) pow[i] = mod_mul(pow[i - 1], B); vector<long long> all_hashes; all_hashes.reserve(8 * size); for (int d = 0; d < 8; d++){ int dx = DX[d], dy = DY[d]; int a = 0, b = 0; if (dx == 0) a = 1; else a = row_num / __gcd(row_num, abs(dx)); if (dy == 0) b = 1; else b = col_num / __gcd(col_num, abs(dy)); int L_dir = a * b / __gcd(a, b); vector<bool> visited(size, false); for (int start = 0; start < size; start++){ if (visited[start]) continue; vector<int> nodes; nodes.reserve(L_dir); int x = start / col_num, y = start % col_num; for (int step = 0; step < L_dir; step++){ int id = x * col_num + y; visited[id] = true; nodes.push_back(id); (x += dx + row_num) %= row_num; (y += dy + col_num) %= col_num; } vector<long long> p_hash(L_dir + 1); p_hash[0] = 0; for (int i = 0; i < L_dir; i++){ int id = nodes[i]; p_hash[i + 1] = (mod_mul(p_hash[i], B) + grid[id / col_num][id % col_num]) % M; } auto pow_repeat = [&](long long exp){ pair<long long, long long> base = {p_hash[L_dir], pow[L_dir]}; pair<long long, long long> res = {0, 1}; while (exp){ if (exp & 1){ res.first = (mod_mul(res.first, base.second) + base.first) % M; res.second = mod_mul(res.second, base.second); } base.first = (mod_mul(base.first, base.second) + base.first) % M; base.second = mod_mul(base.second, base.second); exp >>= 1; } return res; }; for (int p = 0; p < L_dir; p++){ int rem = len; long long curr_hash = 0, curr_pow = 1; int first_len = min(rem, L_dir - p); if (first_len > 0){ long long first_hash = (p_hash[p + first_len] - mod_mul(p_hash[p], pow[first_len]) + M) % M; long long first_pow = pow[first_len]; curr_hash = (mod_mul(curr_hash, first_pow) + first_hash) % M; curr_pow = mod_mul(curr_pow, first_pow); rem -= first_len; } if (rem > 0){ int full_t = rem / L_dir, last_len = rem % L_dir; pair<long long, long long> mid = pow_repeat(full_t); curr_hash = (mod_mul(curr_hash, mid.second) + mid.first) % M; curr_pow = mod_mul(curr_pow, mid.second); if (last_len > 0){ curr_hash = (mod_mul(curr_hash, pow[last_len]) + p_hash[last_len]) % M; curr_pow = mod_mul(curr_pow, pow[last_len]); } } all_hashes.push_back(curr_hash); } } } sort(all_hashes.begin(), all_hashes.end()); long long total = 0; size_t i = 0; while (i < all_hashes.size()){ int cnt = 1; size_t j = i + 1; while (j < all_hashes.size() && all_hashes[i] == all_hashes[j]) cnt++, j++; total += cnt * cnt; i = j; } long long div = (8 * row_num * col_num) * (8 * row_num * col_num); long long gcd = __gcd(total, div); cout << total / gcd << "/" << div / gcd; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...