#pragma GCC optimize("O3,unroll-loops") #include #include #include #include #include using namespace std; int N; int W_edge[105]; vector unused_even; int adj_to[105][5]; int adj_weight[105][5]; int adj_id[105][5]; int adj_deg[105]; bool is_sq[40005]; void build_adj() { for(int i=1; i<=N; ++i) adj_deg[i] = 0; for(int i=1; i i && sum > 0 && is_sq[sum] && !ok[u]) { ok[u] = true; found++; if (found == needed) break; } for(int k = 0; k < adj_deg[u]; ++k) { int v = adj_to[u][k]; if (!((vmask >> v) & 1)) { int nsum = sum + adj_weight[u][k]; if (nsum < 40005 && tail < 4000) { q_u[tail] = v; q_sum[tail] = nsum; q_vis[tail] = vmask | ((unsigned __int128)1 << v); tail++; } } } } missing += (needed - found); } return missing; } struct QState { int u; int sum; unsigned __int128 vis; short path[105]; short len; }; QState q_out[30005]; vector solve_path(int start, int target) { int head = 0, tail = 0; q_out[tail].u = start; q_out[tail].sum = 0; q_out[tail].vis = ((unsigned __int128)1 << start); q_out[tail].len = 0; tail++; while(head < tail) { QState curr = q_out[head++]; if (curr.u == target && curr.sum > 0 && is_sq[curr.sum]) { vector res; for(int i=0; i> v) & 1)) { int nsum = curr.sum + adj_weight[curr.u][k]; if (nsum < 40005 && tail < 30000) { q_out[tail].u = v; q_out[tail].sum = nsum; q_out[tail].vis = curr.vis | ((unsigned __int128)1 << v); for(int p=0; p> N)) return 0; for (int i = 0; i < 40005; ++i) is_sq[i] = false; for (int i = 1; i * i < 40005; ++i) is_sq[i * i] = true; mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); int odd_squares[] = {9, 25, 49, 81, 121, 169, 225, 289, 361}; bool used_init[205] = {false}; for(int k=1; k<=N-2; ++k) { vector magics; for(int s : odd_squares) { int w = s - (2*k - 1); if(w >= 2 && w <= 200 && w % 2 == 0 && !used_init[w]) magics.push_back(w); } if(!magics.empty()) { int chosen = magics[rng() % magics.size()]; W_edge[k] = chosen; used_init[chosen] = true; } else { W_edge[k] = 0; } } for(int i=2; i<=200; i+=2) { if(!used_init[i]) unused_even.push_back(i); } shuffle(unused_even.begin(), unused_even.end(), rng); for(int k=1; k<=N-2; ++k) { if(W_edge[k] == 0) { W_edge[k] = unused_even.back(); unused_even.pop_back(); } } build_adj(); int best_score = evaluate_graph(); int no_improve = 0; while (best_score > 0) { int r1 = rng() % (N - 2) + 1; int type = rng() % 2; int old_w1 = W_edge[r1]; if (type == 0 && !unused_even.empty()) { int idx = rng() % unused_even.size(); int old_w2 = unused_even[idx]; W_edge[r1] = old_w2; build_adj(); int new_score = evaluate_graph(); if (new_score <= best_score) { best_score = new_score; unused_even[idx] = old_w1; no_improve = 0; } else { W_edge[r1] = old_w1; build_adj(); no_improve++; } } else { int r2 = rng() % (N - 2) + 1; if (r1 == r2) continue; swap(W_edge[r1], W_edge[r2]); build_adj(); int new_score = evaluate_graph(); if (new_score <= best_score) { best_score = new_score; no_improve = 0; } else { swap(W_edge[r1], W_edge[r2]); build_adj(); no_improve++; } } if (no_improve > 300) { for(int step=0; step<3; ++step) { int a = rng() % (N - 2) + 1; int b = rng() % (N - 2) + 1; swap(W_edge[a], W_edge[b]); } build_adj(); best_score = evaluate_graph(); no_improve = 0; } } cout << (2 * N - 3) << "\n"; for (int i = 1; i < N; ++i) cout << i << " " << (i + 1) << " " << (2 * i - 1) << "\n"; for (int k = 1; k <= N - 2; ++k) cout << k << " " << (k + 2) << " " << W_edge[k] << "\n"; for (int i = 1; i <= N; ++i) { for (int j = i + 1; j <= N; ++j) { vector path = solve_path(i, j); cout << path.size() << "\n"; for (int k = 0; k < path.size(); ++k) { cout << path[k] << (k == path.size() - 1 ? "" : " "); } cout << "\n"; } } return 0; }