File size: 4,583 Bytes
1fd0050
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <tuple>

using namespace std;

typedef long long ll;

int n = 0;
vector<pair<int, int>> adj[101];

int new_node() {
    return ++n;
}

int any_nodes[21];
map<tuple<ll, ll, int>, int> memo;

int get_len(ll val) {
    if (val == 0) return 1;
    if (val < 0) return 0; // Should not happen
    return 64 - __builtin_clzll(val);
}

int gen(ll l, ll r, int len, int end_node);

void build_chain(int start_node, ll val, int len, int end_node) {
    int curr = start_node;
    for (int i = len - 1; i > 0; --i) {
        int bit = (val >> i) & 1;
        int next_node = new_node();
        adj[curr].push_back({next_node, bit});
        curr = next_node;
    }
    if (len > 0) {
        int bit = val & 1;
        adj[curr].push_back({end_node, bit});
    } else { 
        // A direct connection from start_node to end_node would need a bit.
        // This case is handled by gen returning end_node for len=0,
        // so the caller connects to end_node.
    }
}

int gen(ll l, ll r, int len, int end_node) {
    if (len == 0) return end_node;
    if (l > r) return 0; // Sentinel for no path

    if (memo.count({l, r, len})) {
        return memo.at({l, r, len});
    }

    int start_node = new_node();
    memo[{l, r, len}] = start_node;

    if (l == 0 && r == (1LL << len) - 1) {
        if (len > 0) {
            adj[start_node].push_back({any_nodes[len - 1], 0});
            adj[start_node].push_back({any_nodes[len - 1], 1});
        }
        return start_node;
    }
    
    if (l == r) {
        build_chain(start_node, l, len, end_node);
        return start_node;
    }

    int msb_pos = -1;
    for (int i = len - 1; i >= 0; --i) {
        if (((l >> i) & 1) != ((r >> i) & 1)) {
            msb_pos = i;
            break;
        }
    }

    int curr = start_node;
    for (int i = len - 1; i > msb_pos; --i) {
        int bit = (l >> i) & 1;
        int next_node = new_node();
        adj[curr].push_back({next_node, bit});
        curr = next_node;
    }

    int len_suffix = msb_pos + 1;
    ll mask_suffix = (1LL << len_suffix) - 1;

    // Path for bit 0 at msb_pos
    ll l_for_0_path = l & mask_suffix;
    int child_for_0 = gen(l_for_0_path, mask_suffix, len_suffix, end_node);
    if (child_for_0 != 0) {
        adj[curr].push_back({child_for_0, 0});
    }

    // Path for bit 1 at msb_pos
    ll r_for_1_path = r & mask_suffix;
    int child_for_1 = gen(0, r_for_1_path, len_suffix, end_node);
    if (child_for_1 != 0) {
        adj[curr].push_back({child_for_1, 1});
    }

    return start_node;
}

void solve_range_fixed_len(ll l, ll r) {
    if (l > r) return;
    int d = get_len(l);
    if (l == 0) d = get_len(r); // should not happen with L>=1
    
    ll rem_l = l - (1LL << (d - 1));
    ll rem_r = r - (1LL << (d - 1));
    int u = gen(rem_l, rem_r, d - 1, 2);
    if (u != 0 && u != 2) {
        adj[1].push_back({u, 1});
    } else if (u == 2 && d == 1) { // Special case for number 1
        adj[1].push_back({2, 1});
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    ll L, R;
    cin >> L >> R;

    n = 2; // Start node 1, End node 2

    any_nodes[0] = 2;
    for (int i = 1; i <= 20; ++i) {
        any_nodes[i] = new_node();
    }
    for (int i = 1; i <= 20; ++i) {
        adj[any_nodes[i]].push_back({any_nodes[i - 1], 0});
        adj[any_nodes[i]].push_back({any_nodes[i - 1], 1});
    }
    
    int len_l = get_len(L);
    int len_r = get_len(R);
    
    if (len_l == len_r) {
        solve_range_fixed_len(L, R);
    } else {
        solve_range_fixed_len(L, (1LL << len_l) - 1);
        for (int d = len_l + 1; d < len_r; ++d) {
            solve_range_fixed_len(1LL << (d - 1), (1LL << d) - 1);
        }
        solve_range_fixed_len(1LL << (len_r - 1), R);
    }
    
    int final_n = n;
    if (final_n > 2) {
        // Swap node 2 and node final_n to make final_n the end node
        swap(adj[2], adj[final_n]);
        for(int i=1; i<=final_n; ++i) {
            for(auto& edge : adj[i]) {
                if(edge.first == 2) edge.first = final_n;
                else if (edge.first == final_n) edge.first = 2;
            }
        }
    }
    
    cout << final_n << "\n";
    for (int i = 1; i <= final_n; ++i) {
        sort(adj[i].begin(), adj[i].end());
        cout << adj[i].size();
        for (auto const& [neighbor, weight] : adj[i]) {
            cout << " " << neighbor << " " << weight;
        }
        cout << "\n";
    }

    return 0;
}