Submission #770431

#TimeUsernameProblemLanguageResultExecution timeMemory
770431JakobZorzCubeword (CEOI19_cubeword)C++14
100 / 100
164 ms15124 KiB
#include <iostream> #include <vector> #include <queue> #include <algorithm> #include <set> #include <stack> #include <limits.h> #include <math.h> #include <iomanip> #include <bitset> #include <unordered_map> #include <map> #include <cstring> #include <sstream> #pragma GCC target("popcnt") typedef long long ll; typedef long double ld; using namespace std; const int MOD = 1e9+7; typedef pair<ld,ld> point; #define x first #define y second //#define SEGTREE //#define TREE //#define DSU #define MATH #ifdef SEGTREE template<class Type> class SegmentTree { Type (*func)(Type a, Type b); vector<Type> nodes; vector<int> l; vector<int> r; int size_log2; Type neutral; void init_node(int node) { if(node >= (1 << size_log2)) return; l[2 * node] = l[node]; r[2 * node] = (l[node] + r[node]) / 2; init_node(2 * node); l[2 * node + 1] = (l[node] + r[node]) / 2; r[2 * node + 1] = r[node]; init_node(2 * node + 1); nodes[node] = func(nodes[2 * node], nodes[2 * node + 1]); } void update_node(int node) { if(node < (1 << size_log2)) nodes[node] = func(nodes[2 * node], nodes[2 * node + 1]); if(node != 1) update_node(node / 2); } Type get(int node, int ll_, int rr) { if(rr <= l[node] || ll_ >= r[node]) return neutral; if(ll_ <= l[node] && rr >= r[node]) return nodes[node]; Type left = get(2 * node, ll_, rr); Type right = get(2 * node + 1, ll_, rr); return func(left, right); } public: SegmentTree(Type (*func)(Type a, Type b), vector<Type> vector, Type neutral) : func(func), neutral(neutral) { size_log2 = 0; while((1 << size_log2) < vector.size()) size_log2++; nodes.resize((1 << size_log2) * 2); l.resize((1 << size_log2) * 2); r.resize((1 << size_log2) * 2); for(int i = 0; i < vector.size(); i++) nodes[(1 << size_log2) + i] = vector[i]; l[1] = 0; r[1] = 1 << size_log2; init_node(1); } void set(int idx, Type el) { nodes[(1 << size_log2) + idx] = el; update_node((1 << size_log2) + idx); } Type get(int l, int r) { return get(1, l, r); } Type get(int idx) { return nodes[(1 << size_log2) + idx]; } Type get() { return nodes[1]; } int get_first_larger_or_eq_than(int bound) { return get_first_larger_or_eq_than(1, bound); } int get_first_larger_or_eq_than(int node, int bound) { if(node >= (1 << size_log2)) { return node - (1 << size_log2); } if(nodes[node * 2] > bound) return get_first_larger_or_eq_than(node * 2, bound); else return get_first_larger_or_eq_than(node * 2 + 1, bound - nodes[node * 2]); } }; #endif #ifdef TREE #define POW 18 struct Node { int parents[POW]; vector<int> conns; int depth; int value; int subtree_depth; int subtree_size; int euler; int val; int res; }; ll add(ll a, ll b) { return a + b; } Node nodes[200000]; int n; int setup(int node, int depth, int euler, ll dist) { dist += nodes[node].value; nodes[node].depth = depth; nodes[node].euler = euler++; for(int i = 1; i < POW; i++) { nodes[node].parents[i] = nodes[nodes[node].parents[i - 1]].parents[i - 1]; } int size = 1; for(int i = 0; i < nodes[node].conns.size(); i++) { int child = nodes[node].conns[i]; if(child != nodes[node].parents[0]) { nodes[child].parents[0] = node; euler = setup(child, depth + 1, euler, dist); size += nodes[child].subtree_size; } } nodes[node].subtree_size = size; return euler; } void setup_tree(int root) { nodes[root].parents[0] = root; setup(root, 0, 0, 0); } int get_subtree_depth(int node) { if(nodes[node].subtree_depth) return nodes[node].subtree_depth; int max_depth = 1; for(int child : nodes[node].conns) { if(child == nodes[node].parents[0]) continue; max_depth = max(max_depth, get_subtree_depth(child) + 1); } nodes[node].subtree_depth = max_depth; return max_depth; } int get_parent(int node, int depth) { if(depth > nodes[node].depth) return -1; int climber = node; for(int i = 0; i < POW; i++) { if(depth & (1 << i) && climber != -1) climber = nodes[climber].parents[i]; } return climber; } bool is_sub(int a,int b){ return get_parent(a,nodes[a].depth-nodes[b].depth)==b; } int lca(int a, int b) { if(nodes[a].depth < nodes[b].depth) swap(a, b); a = get_parent(a, nodes[a].depth - nodes[b].depth); if(a == b) return a; for(int i = POW - 1; i >= 0; i--) { if(nodes[a].parents[i] != nodes[b].parents[i]) { a = nodes[a].parents[i]; b = nodes[b].parents[i]; } } return nodes[a].parents[0]; } #endif #ifdef DSU class Dsu { vector<int> arr; int num_sets; public: Dsu(int size) { arr = vector<int>(size, -1); num_sets = size; } int merge(int a, int b) { a = get(a); b = get(b); if(a == b) return a; if(arr[a] > arr[b]) swap(a, b); arr[a] += arr[b]; arr[b] = a; num_sets--; return a; } int get(int a) { if(arr[a] < 0) return a; arr[a] = get(arr[a]); return get(arr[a]); } int get_size(int a) { return -arr[get(a)]; } int get_num_sets() { return num_sets; } }; #endif #ifdef MATH ll dpf[2000001]; ll factorial(ll n) { if(n == 0) return 1; if(dpf[n]) return dpf[n]; ll result = factorial(n - 1) * n; result %= MOD; dpf[n] = result; return result; } ll powm(ll base, ll exp) { ll result = 1; for(int i = 0; i < 64; i++) { if((exp >> i) % 2 == 1) { result *= base; result %= MOD; } base *= base; base %= MOD; } return result; } ll inverse(ll n) { return powm(n, MOD - 2); } ll dpif[2000001]; ll inverse_factorial(ll n) { if(dpif[n]) return dpif[n]; ll result = inverse(factorial(n)); dpif[n] = result; return result; } ll choose(ll n, ll k) { return (((factorial(n)*inverse_factorial(n-k))%MOD)*inverse_factorial(k))%MOD; } ll gcd(ll a, ll b){ if(a==b) return a; if(a<b) swap(a,b); if(b==0) return a; return gcd(b, a%b); } #endif const ll MOD2=998244353; const int NUM_SYMBOLS=62; int char_to_int(char c){ if('a'<=c&&c<='z') return c-'a'; if('A'<=c&&c<='Z') return c-'A'+('z'-'a'+1); return c-'0'+('z'-'a'+1)+('Z'-'A'+1); } bool is_pal(string str){ string rstr=str; reverse(rstr.begin(),rstr.end()); return str==rstr; } ll counts[NUM_SYMBOLS][NUM_SYMBOLS]; ll dp[NUM_SYMBOLS][NUM_SYMBOLS][NUM_SYMBOLS]; int main(){ ios::sync_with_stdio(false); cout.tie(NULL); cin.tie(NULL); //freopen("speeding.in","r",stdin); //freopen("speeding.out","w",stdout); int n; cin>>n; vector<string>strs(n); for(int i=0;i<n;i++){ cin>>strs[i]; string rev=strs[i]; reverse(rev.begin(),rev.end()); if(strs[i]>rev) strs[i]=rev; } set<string>s(strs.begin(),strs.end()); strs={s.begin(),s.end()}; vector<pair<char,char>>arr[11]; for(string str:strs){ int l=(int)str.size(); if(is_pal(str)){ arr[l].emplace_back(str[0],str[0]); }else{ arr[l].emplace_back(str[0],str.back()); if(str[0]==str.back()) arr[l].emplace_back(str[0],str.back()); } } ll res=0; for(int i=3;i<=10;i++){ memset(counts,0,NUM_SYMBOLS*NUM_SYMBOLS*sizeof(ll)); for(auto p:arr[i]){ char c1=p.first; char c2=p.second; counts[char_to_int(c1)][char_to_int(c2)]++; if(c1!=c2) counts[char_to_int(c2)][char_to_int(c1)]++; } #define ITER(c,to) for(int c=0;c<to;c++) memset(dp,0,sizeof(dp)); ITER(c1,NUM_SYMBOLS){ ITER(c2,c1+1){ ITER(c3,c2+1){ ITER(c4,NUM_SYMBOLS){ dp[c1][c2][c3]+=(counts[c1][c4]*counts[c2][c4])%MOD2*counts[c3][c4]; dp[c1][c2][c3]%=MOD2; } } } } ITER(c1,NUM_SYMBOLS){ ITER(c2,c1+1){ ITER(c3,c2+1){ ITER(c4,c3+1){ ll mul=0; int s=(c1==c2)+(c2==c3)+(c3==c4); if(s==0){ mul=24; }else if(s==1){ mul=12; }else if(s==2&&c2!=c3){ mul=6; }else if(s==2){ mul=4; }else if(s==3){ mul=1; } res+=(((mul*dp[c1][c2][c3])%MOD2*dp[c1][c2][c4]%MOD2)*dp[c1][c3][c4]%MOD2)*dp[c2][c3][c4]; res%=MOD2; } } } } } cout<<res<<"\n"; return 0; } /* 3 bac bad cad */
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...