#include using namespace std; static inline bool is_square_int(int x) { if (x <= 0) return false; int r = (int)std::sqrt((double)x); while ((long long)r * r < x) ++r; while ((long long)r * r > x) --r; return (long long)r * r == x; } struct Solver { int N, M; vector> edges; vector w; vector>> adj; explicit Solver(int n): N(n) { for (int k = 1; k <= N - 1; ++k) edges.push_back({k, k + 1}); for (int k = 3; k <= N; ++k) edges.push_back({1, k}); M = (int)edges.size(); adj.assign(N + 1, {}); for (int i = 0; i < M; ++i) { auto [u, v] = edges[i]; adj[u].push_back({v, i}); adj[v].push_back({u, i}); } } vector> candidates_for_pair(int i, int j) { vector> cands; auto add_spine = [&](int a, int b, vector& seq) { if (a < b) { for (int x = a; x < b; ++x) seq.push_back(x - 1); } else if (a > b) { for (int x = a - 1; x >= b; --x) seq.push_back(x - 1); } }; { vector path; add_spine(i, j, path); cands.push_back(path); } vector Ts; Ts.push_back(1); for (int t = 3; t <= i; ++t) Ts.push_back(t); vector Ss; Ss.push_back(1); for (int s = 3; s <= j; ++s) Ss.push_back(s); for (int t : Ts) { for (int s : Ss) { vector path; add_spine(i, t, path); if (t != 1) path.push_back((N - 1) + (t - 3)); if (s != 1) path.push_back((N - 1) + (s - 3)); add_spine(s, j, path); vector usedV(N + 1, 0); int cur = i; usedV[cur] = 1; bool ok = true; for (int eid : path) { auto [u, v] = edges[eid]; int nxt = -1; if (u == cur) nxt = v; else if (v == cur) nxt = u; else { ok = false; break; } if (usedV[nxt]) { ok = false; break; } usedV[nxt] = 1; cur = nxt; } if (ok && cur == j) cands.push_back(path); } } sort(cands.begin(), cands.end()); cands.erase(unique(cands.begin(), cands.end()), cands.end()); return cands; } bool verify_and_collect(const vector>>>& pair_cands, vector>>& ans_paths) { if ((int)w.size() != M) return false; vector used(201, 0); for (int x : w) { if (x < 1 || x > 200 || used[x]) return false; used[x] = 1; } ans_paths.assign(N + 1, vector>(N + 1)); for (int i = 1; i <= N; ++i) { for (int j = i + 1; j <= N; ++j) { bool ok = false; for (auto &p : pair_cands[i][j]) { int sum = 0; for (int eid : p) sum += w[eid]; if (is_square_int(sum)) { ans_paths[i][j] = p; ok = true; break; } } if (!ok) return false; } } return true; } int unsatisfied_count(const vector>>>& pair_cands) { int bad = 0; for (int i = 1; i <= N; ++i) { for (int j = i + 1; j <= N; ++j) { bool ok = false; for (auto &p : pair_cands[i][j]) { int sum = 0; for (int eid : p) sum += w[eid]; if (is_square_int(sum)) { ok = true; break; } } if (!ok) ++bad; } } return bad; } bool construct(vector>>& paths) { vector>>> pair_cands(N + 1, vector>>(N + 1)); for (int i = 1; i <= N; ++i) { for (int j = i + 1; j <= N; ++j) { pair_cands[i][j] = candidates_for_pair(i, j); } } vector spine; for (int k = 1; k <= N - 1; ++k) spine.push_back(2 * k - 1); vector pool; vector used(201, 0); for (int x : spine) used[x] = 1; for (int x = 1; x <= 200; ++x) if (!used[x]) pool.push_back(x); std::mt19937 rng((uint32_t)chrono::high_resolution_clock::now().time_since_epoch().count()); int best_bad = INT_MAX; vector best_w; const int restarts = 120; const int iters = 800; for (int r = 0; r < restarts; ++r) { vector stars = pool; shuffle(stars.begin(), stars.end(), rng); stars.resize(max(0, N - 2)); w = spine; for (int x : stars) w.push_back(x); int cur_bad = unsatisfied_count(pair_cands); if (cur_bad < best_bad) { best_bad = cur_bad; best_w = w; } if (cur_bad == 0 && verify_and_collect(pair_cands, paths)) return true; for (int it = 0; it < iters; ++it) { vector cand_w = w; if (N - 2 >= 2 && (rng() & 1)) { int a = (int)(rng() % (N - 2)); int b = (int)(rng() % (N - 2)); if (a != b) swap(cand_w[(N - 1) + a], cand_w[(N - 1) + b]); } else if (N - 2 >= 1) { vector used_now(201, 0); for (int x : cand_w) used_now[x] = 1; vector unused; for (int x : pool) if (!used_now[x]) unused.push_back(x); if (!unused.empty()) { int pos = (int)(rng() % (N - 2)); cand_w[(N - 1) + pos] = unused[rng() % unused.size()]; } } auto old_w = w; w.swap(cand_w); int nxt_bad = unsatisfied_count(pair_cands); if (nxt_bad < cur_bad || ((rng() % 1000) < 25)) { cur_bad = nxt_bad; if (cur_bad < best_bad) { best_bad = cur_bad; best_w = w; } if (cur_bad == 0 && verify_and_collect(pair_cands, paths)) return true; } else { w.swap(old_w); } } } if (!best_w.empty()) w = best_w; return false; } }; static bool dfs_find_path(int u, int t, const vector>>& g, const vector& w, vector& vis, vector& cur, vector& out, int sum) { if (u == t) { if (is_square_int(sum)) { out = cur; return true; } return false; } for (auto [v, eid] : g[u]) { if (vis[v]) continue; vis[v] = 1; cur.push_back(eid); if (dfs_find_path(v, t, g, w, vis, cur, out, sum + w[eid])) return true; cur.pop_back(); vis[v] = 0; } return false; } static bool emit_small_fan_solution(int N) { vector stars; if (N == 4) stars = {24, 120}; else if (N == 5) stars = {8, 38, 158}; else if (N == 6) stars = {24, 120, 35, 48}; else if (N == 7) stars = {99, 138, 113, 101, 71}; else return false; vector> edges; vector w; for (int k = 1; k <= N - 1; ++k) { edges.push_back({k, k + 1}); w.push_back(2 * k - 1); } for (int k = 3; k <= N; ++k) edges.push_back({1, k}); for (int x : stars) w.push_back(x); int M = (int)edges.size(); vector>> g(N + 1); for (int i = 0; i < M; ++i) { auto [u, v] = edges[i]; g[u].push_back({v, i}); g[v].push_back({u, i}); } vector>> paths(N + 1, vector>(N + 1)); for (int i = 1; i <= N; ++i) { for (int j = i + 1; j <= N; ++j) { vector vis(N + 1, 0), cur, out; vis[i] = 1; if (!dfs_find_path(i, j, g, w, vis, cur, out, 0)) return false; paths[i][j] = out; } } cout << M << '\n'; for (int i = 0; i < M; ++i) { auto [u, v] = edges[i]; cout << u << ' ' << v << ' ' << w[i] << '\n'; } for (int i = 1; i <= N; ++i) { for (int j = i + 1; j <= N; ++j) { cout << paths[i][j].size(); for (int eid : paths[i][j]) cout << ' ' << (eid + 1); cout << '\n'; } } return true; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N; if (!(cin >> N)) return 0; if (N == 2) { cout << 1 << '\n'; cout << "1 2 1\n"; cout << "1 1\n"; return 0; } if (N == 3) { cout << 3 << '\n'; cout << "1 2 16\n"; cout << "2 3 9\n"; cout << "1 3 25\n"; cout << "1 1\n"; cout << "1 3\n"; cout << "1 2\n"; return 0; } if (N <= 7 && emit_small_fan_solution(N)) return 0; Solver solver(N); vector>> paths; bool ok = solver.construct(paths); if (!ok) { cout << solver.M << '\n'; for (int i = 0; i < solver.M; ++i) { auto [u, v] = solver.edges[i]; int ww = (i < (int)solver.w.size() ? solver.w[i] : i + 1); ww = max(1, min(200, ww)); cout << u << ' ' << v << ' ' << ww << '\n'; } for (int i = 1; i <= N; ++i) { for (int j = i + 1; j <= N; ++j) { cout << (j - i); for (int x = i; x < j; ++x) cout << ' ' << x; cout << '\n'; } } return 0; } cout << solver.M << '\n'; for (int i = 0; i < solver.M; ++i) { auto [u, v] = solver.edges[i]; cout << u << ' ' << v << ' ' << solver.w[i] << '\n'; } for (int i = 1; i <= N; ++i) { for (int j = i + 1; j <= N; ++j) { auto &p = paths[i][j]; cout << p.size(); for (int eid : p) cout << ' ' << (eid + 1); cout << '\n'; } } return 0; }