#include <climits>
#include <cstring>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
typedef unsigned long UINT;
typedef signed long SINT;
typedef unsigned long long UINT64;
typedef signed long long SINT64;
[[maybe_unused]] constexpr SINT MAX_SINT = LONG_MAX;
[[maybe_unused]] constexpr UINT MAX_UINT = ULONG_MAX;
[[maybe_unused]] constexpr SINT MAX_SINT64 = LLONG_MAX;
[[maybe_unused]] constexpr UINT MAX_UINT64 = ULLONG_MAX;
// TODO optimize queue
// - vector with pre-reserved size will be okay as it has double-ended access
// - no need to remove queue elems, just skip them
// - mark area under ananlysis (unless it's done already) to avoid repetitive
// queue items
// Benchmark
#ifdef LOCAL
#include "../benchmark.h"
#define BENCH_START bench_time_start();
#define BENCH_M_START(comment) bench_meth_start(comment);
#define BENCH_M_END bench_meth_end();
#else
#define BENCH_START
#define BENCH_M_START(comment)
#define BENCH_M_END
#endif
/** Redirect stdin to provide input with Qt Creator */
void reopenInput(int argc, char** argv) {
#ifdef LOCAL
if (argc > 1) {
auto inFile = argv[1];
cerr << "Reopening stdin to: " << inFile << endl;
auto success = freopen(inFile, "r", stdin);
if (!success) {
cerr << "Error when opening file!" << endl;
cerr << std::strerror(errno) << endl;
}
}
#endif
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static SINT k;
void printNode(SINT a, SINT b) {
cout << a << " " << b << "\n";
}
/**
* It always produces exactly 60 nodes. It is an acceptable simplification.
*
* It can be proven that 60 nodes is enough to draw 10^9 different paths
* (log_2 10^9).
*/
void solve()
{
const SINT last_node = 60;
cout << last_node << "\n";
SINT remaining = k;
SINT curr_node = 1;
while (remaining > 1) {
bool odd = remaining % 2 == 1;
remaining = remaining / 2;
SINT next_node = curr_node + 2;
SINT alternate_node = curr_node + 1;
// print current node
printNode(next_node, alternate_node);
// print alternate node
printNode(next_node, odd ? last_node : -1);
curr_node = next_node;
}
// add node padding so that last node is 100th
while (curr_node < last_node) {
printNode(++curr_node, -1);
}
// print last node
printNode(-1, -1);
cout << flush;
}
int main(int argc, char** argv)
{
BENCH_START
reopenInput(argc, argv);
std::ios::sync_with_stdio(false);
cin >> k;
cerr << "k: " << k << endl;
solve();
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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | #include <climits> #include <cstring> #include <iostream> #include <numeric> #include <vector> using namespace std; typedef unsigned long UINT; typedef signed long SINT; typedef unsigned long long UINT64; typedef signed long long SINT64; [[maybe_unused]] constexpr SINT MAX_SINT = LONG_MAX; [[maybe_unused]] constexpr UINT MAX_UINT = ULONG_MAX; [[maybe_unused]] constexpr SINT MAX_SINT64 = LLONG_MAX; [[maybe_unused]] constexpr UINT MAX_UINT64 = ULLONG_MAX; // TODO optimize queue // - vector with pre-reserved size will be okay as it has double-ended access // - no need to remove queue elems, just skip them // - mark area under ananlysis (unless it's done already) to avoid repetitive // queue items // Benchmark #ifdef LOCAL #include "../benchmark.h" #define BENCH_START bench_time_start(); #define BENCH_M_START(comment) bench_meth_start(comment); #define BENCH_M_END bench_meth_end(); #else #define BENCH_START #define BENCH_M_START(comment) #define BENCH_M_END #endif /** Redirect stdin to provide input with Qt Creator */ void reopenInput(int argc, char** argv) { #ifdef LOCAL if (argc > 1) { auto inFile = argv[1]; cerr << "Reopening stdin to: " << inFile << endl; auto success = freopen(inFile, "r", stdin); if (!success) { cerr << "Error when opening file!" << endl; cerr << std::strerror(errno) << endl; } } #endif } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ static SINT k; void printNode(SINT a, SINT b) { cout << a << " " << b << "\n"; } /** * It always produces exactly 60 nodes. It is an acceptable simplification. * * It can be proven that 60 nodes is enough to draw 10^9 different paths * (log_2 10^9). */ void solve() { const SINT last_node = 60; cout << last_node << "\n"; SINT remaining = k; SINT curr_node = 1; while (remaining > 1) { bool odd = remaining % 2 == 1; remaining = remaining / 2; SINT next_node = curr_node + 2; SINT alternate_node = curr_node + 1; // print current node printNode(next_node, alternate_node); // print alternate node printNode(next_node, odd ? last_node : -1); curr_node = next_node; } // add node padding so that last node is 100th while (curr_node < last_node) { printNode(++curr_node, -1); } // print last node printNode(-1, -1); cout << flush; } int main(int argc, char** argv) { BENCH_START reopenInput(argc, argv); std::ios::sync_with_stdio(false); cin >> k; cerr << "k: " << k << endl; solve(); return 0; } |
English