| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| int main() { |
| ios::sync_with_stdio(false); |
| cin.tie(nullptr); |
| |
| long long L, R; |
| if (!(cin >> L >> R)) return 0; |
|
|
| |
| struct Interval { long long b; int k; }; |
| vector<Interval> intervals; |
| long long cur = L; |
| int M = 0; |
| while (cur <= R) { |
| int tz = __builtin_ctzll(cur); |
| long long rem = R - cur + 1; |
| int maxk = 63 - __builtin_clzll(rem); |
| int k = min(tz, maxk); |
| intervals.push_back({cur, k}); |
| M = max(M, k); |
| cur += 1LL << k; |
| } |
|
|
| |
| |
| vector<vector<pair<int,int>>> adj; |
| vector<array<int,2>> contNext; |
| adj.resize(3); |
| contNext.resize(3); |
| contNext[1] = {0,0}; |
| contNext[2] = {0,0}; |
| int S = 1, T = 2; |
| int nNodes = 2; |
|
|
| auto newNode = [&]() { |
| ++nNodes; |
| adj.resize(nNodes+1); |
| contNext.resize(nNodes+1); |
| contNext[nNodes] = {0,0}; |
| return nNodes; |
| }; |
|
|
| unordered_set<long long> edgeSet; |
| edgeSet.reserve(4096); |
| auto addEdge = [&](int u, int v, int w){ |
| long long key = ((long long)u << 40) ^ ((long long)v << 1) ^ (long long)w; |
| if (edgeSet.insert(key).second) { |
| adj[u].push_back({v, w}); |
| } |
| }; |
|
|
| |
| vector<int> G; |
| if (M > 0) { |
| G.resize(M); |
| for (int i = 0; i < M; ++i) { |
| G[i] = newNode(); |
| } |
| for (int i = 0; i < M-1; ++i) { |
| addEdge(G[i], G[i+1], 0); |
| addEdge(G[i], G[i+1], 1); |
| } |
| addEdge(G[M-1], T, 0); |
| addEdge(G[M-1], T, 1); |
| } |
|
|
| auto bitlen = [&](long long x)->int{ |
| return (x == 0) ? 0 : (64 - __builtin_clzll(x)); |
| }; |
|
|
| |
| for (auto itv : intervals) { |
| long long b = itv.b; |
| int k = itv.k; |
| long long p = b >> k; |
| int lenp = bitlen(p); |
| int curNode = S; |
|
|
| for (int i = lenp - 1; i >= 0; --i) { |
| int bit = (p >> i) & 1; |
| if (i == 0 && k == 0) { |
| |
| addEdge(curNode, T, bit); |
| } else { |
| |
| if (contNext[curNode][bit] == 0) { |
| int nx = newNode(); |
| addEdge(curNode, nx, bit); |
| contNext[curNode][bit] = nx; |
| } |
| curNode = contNext[curNode][bit]; |
| } |
| } |
|
|
| if (k > 0) { |
| int target = G[M - k]; |
| |
| addEdge(curNode, target, 0); |
| addEdge(curNode, target, 1); |
| } |
| } |
|
|
| |
| cout << nNodes << '\n'; |
| for (int u = 1; u <= nNodes; ++u) { |
| cout << (int)adj[u].size(); |
| for (auto &e : adj[u]) { |
| cout << ' ' << e.first << ' ' << e.second; |
| } |
| cout << '\n'; |
| } |
|
|
| return 0; |
| } |