Submission #198106

#TimeUsernameProblemLanguageResultExecution timeMemory
198106model_codeCubeword (CEOI19_cubeword)C++17
100 / 100
858 ms27160 KiB
#pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #include <bits/stdc++.h> using namespace std; class Solver { constexpr static unsigned long long MOD = 998244353; constexpr static int MAX_L = 10; constexpr static int MAX_CHAR_ID = 62; vector<string> words[MAX_L+1]; unsigned char rotations[1<<24]; inline int encode_char(char c) { if(c >= 'a' && c <= 'z') return c-'a'; else if(c >= 'A' && c <= 'Z') return c-'A'+26; else // if(c >= '0' && c <= '9') return c-'0'+52; } inline bool unpack(int packed_seq, int * seq) { for(int i = 0; i < 4; i++) { seq[3-i] = packed_seq & 63; if(seq[3-i] >= MAX_CHAR_ID) return false; packed_seq >>= 6; } return true; } inline int pack(int * seq) { int ret = 0; for(int i = 0; i < 4; i++) ret = (ret << 6) | seq[i]; return ret; } unsigned long long solve(int L) { unsigned int cnt_by_end_chars[MAX_CHAR_ID][MAX_CHAR_ID]; memset(cnt_by_end_chars, 0, sizeof(cnt_by_end_chars)); set<string> w; for(string & word : words[L]) { w.insert(word); reverse(word.begin(), word.end()); w.insert(word); } for(const string & word : w) { int start_char_id = encode_char(word[0]); int end_char_id = encode_char(word[L-1]); cnt_by_end_chars[start_char_id][end_char_id]++; } unsigned int cnt_by_vertices[MAX_CHAR_ID][MAX_CHAR_ID][MAX_CHAR_ID]; memset(cnt_by_vertices, 0, sizeof(cnt_by_vertices)); int seq[4]; for(int i = 0; i < (1<<18); i++) { if(!unpack(i<<6, seq)) continue; unsigned long long sum_cnt = 0; for(int j = 0; j < MAX_CHAR_ID; j++) { unsigned long long cnt = 1; for(int k = 0; k < 3; k++) cnt = cnt * cnt_by_end_chars[seq[k]][j]; sum_cnt += cnt; if(sum_cnt >= 5*MOD*MOD) sum_cnt -= 5*MOD*MOD; } cnt_by_vertices[seq[0]][seq[1]][seq[2]] = sum_cnt % MOD; } unsigned long long ret = 0; for(int i = 0; i < (1<<24); i++) if(rotations[i]) { if(!unpack(i, seq)) continue; unsigned long long cnt = rotations[i]; int V_seq[3]; for(int j = 0; j < 3; j++) V_seq[j] = seq[j]; for(int j = 0; j < 4; j++) { cnt = cnt * cnt_by_vertices[V_seq[0]][V_seq[1]][V_seq[2]] % MOD; if(j < 3) V_seq[2-j] = seq[3-j]; } ret += cnt; if(ret >= MOD) ret -= MOD; } return ret; } public: Solver(vector<string> words_) { for(int i = 0; i < (int)words_.size(); i++) { string w = words_[i]; words[w.length()].push_back(w); } memset(rotations, 0, sizeof(rotations)); int seq_sorted[4]; for(int i = 0; i < (1<<24); i++) { if(!unpack(i, seq_sorted)) continue; for(int j = 0; j < 3; j++) for(int k = 1; k < 4; k++) if(seq_sorted[j] > seq_sorted[k]) swap(seq_sorted[j], seq_sorted[k]); rotations[pack(seq_sorted)]++; } } unsigned long long solve() { unsigned long long ret = 0; for(int l = 2; l <= MAX_L; l++) { ret += solve(l); if(ret >= MOD) ret -= MOD; } return ret; } }; int main() { cin.sync_with_stdio(0); int N; cin >> N; vector<string> words(N); for(int i = 0; i < N; i++) cin >> words[i]; Solver solver(words); cout << solver.solve() << "\n"; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...