/*
* Copyright (C) 2020 Paweł Widera
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
* http://www.gnu.org/licenses/gpl.html
*/
#include <cmath>
#include <iostream>
#include <vector>
#include <list>
#include <bitset>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int k;
cin >> k;
// special case
if (k == 1) {
cout << "2" << endl << "2 -1" << endl << "-1 -1" << endl;
return 0;
}
bitset<32> bits(k);
int extra = max(2, (int)bits.count() - 1);
int n = 2 * (int)log2(k) + extra - 1;
int prime_node = extra + 1;
vector<list<int>> graph(n);
// connect all nodes in a straight line
for (int i = 0; i < n; ++i) {
graph[i].emplace_back(i + 1);
}
/* Add alternative paths in two halves (top and bottom):
* - bottom half encodes the highest bit - 2 ** log2(k)
* - top reuses bottom edges to encode the 2 ** e - 1 states
* (it requires one extra node per edge)
*
* /^^^^^^^^^^^^^^\ = 1
* /^^^/^^^^^^^^^\ \ = 2
* /^^/^^^/^^^\ \ \ = 4
* O---O---O---O---X---O---O---O---O (X is prime node)
* \______________/\______/\_______/ = 8
*/
// bottom half - all edges connected
for (int i = n; i > prime_node; i -= 2) {
graph[i - 2].emplace_back(i);
}
graph[0].emplace_back(prime_node);
// top half - edges represent the bits needed
int index = 0;
int size = (int)log2(k) - 1;
for (int i = 0; i <= size; ++i) {
if (bits[size - i]) {
graph[++index].emplace_back(prime_node + 2*i);
}
}
// print graph
cout << n + 1 << endl;
int i = 0;
for (auto list: graph) {
int edge = list.front() == list.back() ? -2 : list.back();
cout << list.front() + 1 << " " << edge + 1 << endl;
}
cout << "-1 -1" << endl;
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | /* * Copyright (C) 2020 Paweł Widera * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details: * http://www.gnu.org/licenses/gpl.html */ #include <cmath> #include <iostream> #include <vector> #include <list> #include <bitset> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int k; cin >> k; // special case if (k == 1) { cout << "2" << endl << "2 -1" << endl << "-1 -1" << endl; return 0; } bitset<32> bits(k); int extra = max(2, (int)bits.count() - 1); int n = 2 * (int)log2(k) + extra - 1; int prime_node = extra + 1; vector<list<int>> graph(n); // connect all nodes in a straight line for (int i = 0; i < n; ++i) { graph[i].emplace_back(i + 1); } /* Add alternative paths in two halves (top and bottom): * - bottom half encodes the highest bit - 2 ** log2(k) * - top reuses bottom edges to encode the 2 ** e - 1 states * (it requires one extra node per edge) * * /^^^^^^^^^^^^^^\ = 1 * /^^^/^^^^^^^^^\ \ = 2 * /^^/^^^/^^^\ \ \ = 4 * O---O---O---O---X---O---O---O---O (X is prime node) * \______________/\______/\_______/ = 8 */ // bottom half - all edges connected for (int i = n; i > prime_node; i -= 2) { graph[i - 2].emplace_back(i); } graph[0].emplace_back(prime_node); // top half - edges represent the bits needed int index = 0; int size = (int)log2(k) - 1; for (int i = 0; i <= size; ++i) { if (bits[size - i]) { graph[++index].emplace_back(prime_node + 2*i); } } // print graph cout << n + 1 << endl; int i = 0; for (auto list: graph) { int edge = list.front() == list.back() ? -2 : list.back(); cout << list.front() + 1 << " " << edge + 1 << endl; } cout << "-1 -1" << endl; return 0; } |
English