| #include <iostream> |
| #include <vector> |
| #include <string> |
| #include <algorithm> |
| #include <cmath> |
|
|
| using namespace std; |
|
|
| |
| vector<pair<int, int>> adj[101]; |
| |
| int num_nodes = 2; |
|
|
| |
| int len(long long n) { |
| if (n == 0) return 1; |
| return floor(log2(n)) + 1; |
| } |
|
|
| |
| string to_binary(long long n, int l) { |
| if (l == 0) return ""; |
| string bin; |
| for (int i = l - 1; i >= 0; i--) { |
| bin += ((n >> i) & 1) ? '1' : '0'; |
| } |
| return bin; |
| } |
|
|
| |
| void add_edge(int u, int v, int w) { |
| adj[u].push_back({v, w}); |
| } |
|
|
| |
| |
| |
| int target_for_gen_node(int k) { |
| if (k == 0) return 2; |
| return k + 2; |
| } |
|
|
| |
| |
| void gen_ge(long long val, int l, int start_node) { |
| string s = to_binary(val, l); |
| int curr = start_node; |
| for (int i = 0; i < l; ++i) { |
| |
| |
| |
| if (i > 0 && s[i] == '0') { |
| add_edge(curr, target_for_gen_node(l - 1 - i), 1); |
| } |
| |
| |
| int next_node = (i == l - 1) ? 2 : ++num_nodes; |
| add_edge(curr, next_node, s[i] - '0'); |
| curr = next_node; |
| } |
| } |
|
|
| |
| |
| void gen_le(long long val, int l, int start_node) { |
| string s = to_binary(val, l); |
| int curr = start_node; |
| for (int i = 0; i < l; ++i) { |
| |
| |
| |
| if (i > 0 && s[i] == '1') { |
| add_edge(curr, target_for_gen_node(l - 1 - i), 0); |
| } |
| |
| |
| int next_node = (i == l - 1) ? 2 : ++num_nodes; |
| add_edge(curr, next_node, s[i] - '0'); |
| curr = next_node; |
| } |
| } |
|
|
| |
| void gen_ge_suf(long long val, int l, int start_node) { |
| if (l <= 0) return; |
| string s = to_binary(val, l); |
| int curr = start_node; |
| for (int i = 0; i < l; ++i) { |
| if (s[i] == '0') { |
| add_edge(curr, target_for_gen_node(l - 1 - i), 1); |
| } |
| int next_node = (i == l - 1) ? 2 : ++num_nodes; |
| add_edge(curr, next_node, s[i] - '0'); |
| curr = next_node; |
| } |
| } |
|
|
| |
| void gen_le_suf(long long val, int l, int start_node) { |
| if (l <= 0) return; |
| string s = to_binary(val, l); |
| int curr = start_node; |
| for (int i = 0; i < l; ++i) { |
| if (s[i] == '1') { |
| add_edge(curr, target_for_gen_node(l - 1 - i), 0); |
| } |
| int next_node = (i == l - 1) ? 2 : ++num_nodes; |
| add_edge(curr, next_node, s[i] - '0'); |
| curr = next_node; |
| } |
| } |
|
|
| |
| void gen_path(long long val, int l, int start_node) { |
| string s = to_binary(val, l); |
| int curr = start_node; |
| for (int i = 0; i < l; ++i) { |
| int next_node = (i == l - 1) ? 2 : ++num_nodes; |
| add_edge(curr, next_node, s[i] - '0'); |
| curr = next_node; |
| } |
| } |
|
|
| int main() { |
| ios_base::sync_with_stdio(false); |
| cin.tie(NULL); |
|
|
| long long L, R; |
| cin >> L >> R; |
|
|
| |
| for (int i = 1; i <= 20; ++i) { |
| num_nodes = max(num_nodes, i + 2); |
| add_edge(i + 2, target_for_gen_node(i - 1), 0); |
| add_edge(i + 2, target_for_gen_node(i - 1), 1); |
| } |
| |
| |
| num_nodes = 22; |
|
|
| if (L == R) { |
| gen_path(L, len(L), 1); |
| } else { |
| int lenL = len(L); |
| int lenR = len(R); |
|
|
| if (lenL < lenR) { |
| |
| gen_ge(L, lenL, 1); |
| |
| |
| for (int k = lenL + 1; k < lenR; ++k) { |
| |
| add_edge(1, target_for_gen_node(k - 1), 1); |
| } |
| |
| |
| gen_le(R, lenR, 1); |
| } else { |
| int k = lenL; |
| string binL = to_binary(L, k); |
| string binR = to_binary(R, k); |
|
|
| int p = 0; |
| while (p < k && binL[p] == binR[p]) { |
| p++; |
| } |
|
|
| |
| int curr = 1; |
| for (int i = 0; i < p; ++i) { |
| int next_node = ++num_nodes; |
| add_edge(curr, next_node, binL[i] - '0'); |
| curr = next_node; |
| } |
|
|
| int common_node = curr; |
| int len_suf = k - p - 1; |
|
|
| |
| int l_branch_start = ++num_nodes; |
| add_edge(common_node, l_branch_start, 0); |
| long long l_suf_val = L & ((1LL << len_suf) - 1); |
| gen_ge_suf(l_suf_val, len_suf, l_branch_start); |
|
|
| |
| int r_branch_start = ++num_nodes; |
| add_edge(common_node, r_branch_start, 1); |
| long long r_suf_val = R & ((1LL << len_suf) - 1); |
| gen_le_suf(r_suf_val, len_suf, r_branch_start); |
| } |
| } |
|
|
| cout << num_nodes << endl; |
| for (int i = 1; i <= num_nodes; ++i) { |
| cout << adj[i].size(); |
| |
| sort(adj[i].begin(), adj[i].end()); |
| for (auto& edge : adj[i]) { |
| cout << " " << edge.first << " " << edge.second; |
| } |
| cout << endl; |
| } |
|
|
| return 0; |
| } |