#include #include #include #include #include using namespace std; const int MAX_SUM = 50000; bool is_sq_arr[MAX_SUM + 5]; inline bool is_sq(int n) { if (n < 0 || n > MAX_SUM) return false; return is_sq_arr[n]; } int N; int W[105]; int Dist[105][105]; vector get_tree_path(int a, int b) { vector path; if (a < b) { for (int k = a; k < b; ++k) path.push_back(k); } else { for (int k = a - 1; k >= b; --k) path.push_back(k); } return path; } inline int get_shortcut_id(int x) { if (x == 2) return 1; return N + x - 3; } struct Pair { int u, v; }; int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); for (int i = 0; i * i <= MAX_SUM; ++i) { is_sq_arr[i * i] = true; } if (!(cin >> N)) return 0; if (N == 2) { cout << 1 << "\n"; cout << 1 << " " << 2 << " " << 1 << "\n"; cout << 1 << " " << 1 << "\n"; return 0; } for (int i = 1; i <= N; ++i) { for (int j = 1; j <= N; ++j) { Dist[i][j] = abs((i - 1) * (i - 1) - (j - 1) * (j - 1)); } } vector evens; for (int i = 2; i <= 200; i += 2) { evens.push_back(i); } vector pairs_to_check; for (int d = 1; d <= N - 1; ++d) { for (int u = 2; u + d <= N; ++u) { pairs_to_check.push_back({u, u + d}); } } mt19937 rng(42); while (true) { shuffle(evens.begin(), evens.end(), rng); for (int i = 3; i <= N; ++i) { W[i] = evens[i - 3]; } W[2] = 1; bool all_ok = true; for (const auto& p : pairs_to_check) { int u = p.u; int v = p.v; if (is_sq_arr[Dist[u][v]]) continue; bool found = false; for (int x = 2; x < v; ++x) { int left_part = Dist[u][x] + W[x]; int start_y = max(u, x) + 1; for (int y = start_y; y <= N; ++y) { if (is_sq_arr[left_part + W[y] + Dist[y][v]]) { found = true; break; } } if (found) break; } if (!found) { all_ok = false; break; } } if (all_ok) break; } int M = 2 * N - 3; cout << M << "\n"; for (int i = 1; i < N; ++i) { cout << i << " " << i + 1 << " " << 2 * i - 1 << "\n"; } for (int i = 3; i <= N; ++i) { cout << 1 << " " << i << " " << W[i] << "\n"; } for (int u = 1; u <= N; ++u) { for (int v = u + 1; v <= N; ++v) { if (u == 1 || is_sq_arr[Dist[u][v]]) { vector path = get_tree_path(u, v); cout << path.size(); for (int e : path) cout << " " << e; cout << "\n"; continue; } bool printed = false; for (int x = 2; x < v && !printed; ++x) { int start_y = max(u, x) + 1; for (int y = start_y; y <= N && !printed; ++y) { if (is_sq_arr[Dist[u][x] + W[x] + W[y] + Dist[y][v]]) { vector path; vector p1 = get_tree_path(u, x); path.insert(path.end(), p1.begin(), p1.end()); path.push_back(get_shortcut_id(x)); path.push_back(get_shortcut_id(y)); vector p2 = get_tree_path(y, v); path.insert(path.end(), p2.begin(), p2.end()); cout << path.size(); for (int e : path) cout << " " << e; cout << "\n"; printed = true; } } } } } return 0; }