AtCoder Beginner Contest 108 - All Your Paths are Different Lengths

You are given an integer L. Construct a directed graph that satisfies the conditions below. The graph may contain multiple edges between the same pair of vertices. It can be proved that such a graph always exists.
 - The number of vertices, N, is at most 20. The vertices are given ID numbers from 1 to N.
 - The number of edges, M, is at most 60. Each edge has an integer length between 0 and 10^6 (inclusive).
 - Every edge is directed from the vertex with the smaller ID to the vertex with the larger ID. That is, 1,2,...,N is one possible topological order of the vertices.
 - There are exactly L different paths from Vertex 1 to Vertex N. The lengths of these paths are all different, and they are integers between 0 and L-1.
Here, the length of a path is the sum of the lengths of the edges contained in that path, and two paths are considered different when the sets of the edges contained in those paths are different.

-----Constraints-----
 - 2 \leq L \leq 10^6
 - L is an integer.

-----Input-----
Input is given from Standard Input in the following format:
L

-----Output-----
In the first line, print N and M, the number of the vertices and edges in your graph.
In the i-th of the following M lines, print three integers u_i,v_i and w_i, representing the starting vertex, the ending vertex and the length of the i-th edge.
If there are multiple solutions, any of them will be accepted.

-----Sample Input-----
4

-----Sample Output-----
8 10
1 2 0
2 3 0
3 4 0
1 5 0
2 6 0
3 7 0
4 8 0
5 6 1
6 7 1
7 8 1

In the graph represented by the sample output, there are four paths from Vertex 1 to N=8:
 - 1 → 2 → 3 → 4 → 8 with length 0
 - 1 → 2 → 3 → 7 → 8 with length 1
 - 1 → 2 → 6 → 7 → 8 with length 2
 - 1 → 5 → 6 → 7 → 8 with length 3
There are other possible solutions.

Source: atcoder | Difficulty: MEDIUM


Solutions:
L = int(input())
node = 0
for i in range(21):
	if L < 2 ** i:
		L2 = 2 ** (i - 1)
		N = i
		node = i - 1
		break
l = L - L2
L_reg = L2
L_tmp = L2
L_new = L2
L_bai = 1
a = []
b = []

def make_arr(init, N, a, b):
	global L_reg
	global L_tmp
	global L_new
	global L_bai
	L_new = L_reg
	if [init, N] in a:
		L_tmp = L_new - L_bai
		L_bai *= 2
		make_arr(init + 1, N, a, b)
		a.remove([init, N])
		b.remove(max(b))
	else:
		a.append([init, N])
		b.append(L_new)
		L_reg += 1
		L_bai = 1
for i in range(l):
	make_arr(1, N, a, b)
for i in range(len(a)):
	a[i].append(b[i])
arr_0 = []
arr_2 = []
for i in range(node):
	arr_0.append([i + 1, i + 2, 0])
	arr_2.append([i + 1, i + 2, 2 ** i])
print(node + 1, len(arr_0) + len(arr_2) + len(a))
for i in arr_0:
	print(i[0], i[1], i[2])
for i in arr_2:
	print(i[0], i[1], i[2])
for i in a:
	print(i[0], i[1], i[2])


import math
l = int(input())
n = int(math.log2(l) + 1)
E = []
for i in range(n - 1):
	E.append([i + 1, i + 2, 0])
	E.append([i + 1, i + 2, 2 ** i])
i = n - 2
while l > 2 ** (n - 1):
	t = l - 2 ** i
	if t > 2 ** (n - 1) - 1:
		E.append([i + 1, n, t])
		l = t
	i -= 1
print(n, len(E))
for i in range(len(E)):
	print(*E[i])


from math import log2
L = int(input())
n = int(log2(L))
print(n + 1, format(L, 'b').count('1') - 1 + 2 * n)
Li = 1
for i in range(n):
	print(i + 1, i + 2, 0)
	print(i + 1, i + 2, Li)
	Li *= 2
mask = 2
for i in range(n):
	if L >> i & 1:
		print(i + 1, n + 1, L - (L & mask - 1))
	mask *= 2


L = int(input())
N = 2
while 2 ** N - 1 <= L - 1:
	N += 1
edge = []
for i in range(1, N):
	edge.append([i, i + 1, 0])
	edge.append([i, i + 1, 2 ** (i - 1)])
for i in reversed(range(1, N)):
	if L - 2 ** (i - 1) > 2 ** (N - 1) - 1:
		edge.append([i, N, L - 2 ** (i - 1)])
		L = L - 2 ** (i - 1)
print(N, len(edge))
for x in edge:
	print(*x)


l = int(input())
r = 1
while 2 ** r <= l:
	r += 1
r = min(19, r - 1)
n = r + 1
ts = [i for i in range(1, n)]
ts.reverse()
m = (n - 1) * 2
points = {}
for t in ts:
	a = l - 2 ** (t - 1)
	b = 2 ** r
	if a >= b:
		points[t] = a
		l -= 2 ** (t - 1)
m += len(points)
print((n, m))
for i in range(1, (n - 1) * 2 + 1):
	p = (i - 1) // 2 + 1
	if i % 2 == 0:
		print((p, p + 1, 0))
	else:
		print((p, p + 1, 2 ** (p - 1)))
for k in list(points.keys()):
	print((k, n, points[k]))


L = int(input())
N = len(bin(L)) - 2
nodes = []
for i in range(N - 1):
	(u1, v1, w1) = (i + 1, i + 2, 0)
	(u2, v2, w2) = (i + 1, i + 2, 1 << i)
	nodes.append([u1, v1, w1])
	nodes.append([u2, v2, w2])
for i in range(1, N):
	if L >> i - 1 & 1 == 1:
		(u, v, w) = (i, N, L >> i << i)
		nodes.append([u, v, w])
M = len(nodes)
print(N, M)
for i in range(M):
	(u, v, w) = nodes[i]
	print(u, v, w)


l = int(input())
l -= 1
to = [[] for _ in range(14)]
for i in range(1, 13):
	to[i].append((i + 1, 0 * 3 ** (12 - i)))
	to[i].append((i + 1, 1 * 3 ** (12 - i)))
	to[i].append((i + 1, 2 * 3 ** (12 - i)))
d = []
l_upto = []
t = l
s = 0
for i in range(13):
	d.append(t % 3)
	s += t % 3 * 3 ** i
	l_upto.append(s)
	t //= 3
for (i, t) in enumerate(d):
	for s in range(t + (i == 0)):
		to[0].append((13 - i, l - l_upto[i] + 3 ** i * s))
print(14, sum(map(len, to)))
for i in range(len(to)):
	for (j, cost) in to[i]:
		print(i + 1, j + 1, cost)


from itertools import dropwhile
l = int(input())
k = [l >> i & 1 for i in range(20)][::-1]
k = list(dropwhile(lambda x: x == 0, k))
n = len(k)
path = []
for i in range(n - 1):
	path.append((i + 1, i + 2, 0))
	path.append((i + 1, i + 2, 2 ** i))
path_len = 2 ** (n - 1)
for i in range(1, n):
	if k[i]:
		x = n - 1 - i
		path.append((x + 1, n, path_len))
		path_len += 2 ** x
m = len(path)
print(n, m)
for i in path:
	print(i[0], i[1], i[2])


L = int(input())
x = L
xs1 = []
xs2 = []
xs3 = []
for i in range(19):
	c = 18 - i
	xs1.append((i + 1, i + 2, 0))
b = 0
for i in range(20):
	n = 19 - i
	r = 2 ** n
	if x >= r:
		m = n
		x -= r
		b += r
		break
for i in range(i + 1, 20):
	n = 19 - i
	r = 2 ** n
	if x >= r:
		xs3.append((n + 1, 20, b))
		x -= r
		b += r
for i in range(m):
	xs2.append((i + 1, i + 2, 2 ** i))
xs = xs1 + xs2 + xs3
print(20, len(xs))
for x in xs:
	print(*x)


import math
l = int(input())
n = math.floor(math.log2(l))
edge = []
for i in range(n):
	edge.append((i + 1, i + 2, 0))
	edge.append((i + 1, i + 2, 2 ** i))
i = n - 1
while l > 2 ** n:
	m = l - 2 ** i
	if m >= 2 ** n:
		edge.append((i + 1, n + 1, m))
		l = m
	i -= 1
print(n + 1, len(edge))
for (a, b, c) in edge:
	print(a, b, c)


L = int(input())
r = 0
while 1:
	r += 1
	if 2 ** r > L or r == 20:
		N = r
		break
path = []
for i in range(1, N):
	path.append([i, i + 1, 0])
	path.append([i, i + 1, 2 ** (i - 1)])
for t in range(N - 1, 0, -1):
	if L - 2 ** (t - 1) > 2 ** (N - 1) - 1:
		path.append([t, N, L - 2 ** (t - 1)])
		L -= 2 ** (t - 1)
M = len(path)
print('{} {}'.format(N, M))
for i in range(M):
	print(' '.join(map(str, path[i])))


l = int(input())
n = len(bin(l - 1)) - 2
V = []
if all([l - 1 >> i & 1 for i in range(n)]):
	n += 1
	for i in range(n - 1):
		V.append([i + 1, i + 2, 0])
		V.append([i + 1, i + 2, 2 ** (n - i - 2)])
else:
	for i in range(n - 1):
		V.append([i + 1, i + 2, 0])
		V.append([i + 1, i + 2, 2 ** (n - i - 2)])
	now = 2 ** (n - 1)
	for i in range(n - 2):
		if l - 1 >> n - i - 2 & 1:
			V.append([1, i + 2, now])
			now += 2 ** (n - i - 2)
	if l - 1 & 1:
		V.append([1, n - 1, now])
	else:
		V.append([1, n, now])
print(n, len(V))
for v in V:
	print(*v)


L = int(input())
N = len(bin(L)[2:])
ans = []
for i in range(1, N):
	ans.append((i, i + 1, 0))
	ans.append((i, i + 1, 1 << i - 1))
n = 1 << N - 1
while n < L:
	i = 1
	while (1 << i) - 1 + n < L:
		i += 1
	ans.append((i, N, n))
	n += 1 << i - 1
print(N, len(ans))
for a in ans:
	print(*a)


L = int(input())
B = bin(L)
N = len(B) - 2
print(N, 2 * N + B.count('1') - 3)
for i in range(1, N):
	print(i, i + 1, 0)
	print(i, i + 1, 2 ** (i - 1))
	if int(B[N + 2 - i]):
		print(i, N, L - 2 ** (i - 1))
		L -= 2 ** (i - 1)


L = int(input())
bL = bin(L)[2:]
N = len(bL)
L = 2 * (N - 1) + bL[1:].count('1')
print(N, L)
for (i, b) in enumerate(bL[1:]):
	if b == '1':
		print(1, i + 2, 0)
(M, m) = (0, 0)
for (i, b) in enumerate(bL[:0:-1]):
	add = M - m + 1
	if b == '1':
		print(N - i - 1, N - i, add)
		print(N - i - 1, N - i, 2 * add)
		m += add
		M += 2 * add
	else:
		print(N - i - 1, N - i, 0)
		print(N - i - 1, N - i, add)
		M += add


L = int(input())
n = L.bit_length()
ans = []
for i in range(1, n):
	ans.append((i, i + 1, 0))
	ans.append((i, i + 1, 2 ** (n - i - 1)))
binL = bin(L)
for i in range(1, n):
	if binL[i + 2] == '1':
		mask = int(binL[:i + 2], 2) << n - i
		ans.append((1, i + 1, L & mask))
print(n, len(ans))
for edge in ans:
	print(*edge)


L = int(input())
ret = []
count = 0
for i in range(19, 0, -1):
	while L - (1 << i - 1) >= 0:
		ret.append((i, count))
		count += 1 << i - 1
		L -= 1 << i - 1
N = ret[0][0]
M = len(ret) + 2 * (N - 1)
print(N + 1, M)
for i in range(1, N):
	print(i, i + 1, 0)
	print(i, i + 1, 1 << i - 1)
for r in ret:
	print(r[0], N + 1, r[1])


L = int(input())
N = L.bit_length()
n = []
for i in range(1, N):
	n += [[i, i + 1, 0], [i, i + 1, 2 ** (i - 1)]]
v = 2 ** (N - 1) - 1
while L - 1 - v > 0:
	b = min(N - 1, (L - 1 - v).bit_length())
	n += [[b, N, v + 1]]
	v += 2 ** (b - 1)
M = len(n)
print(N, M)
for _ in n:
	print(*_)


def d_all_your_paths_are_different_lengths(L):
	do = []
	while L > 2:
		if L % 2 == 0:
			do.append('*2')
			L >>= 1
		else:
			do.append('+1')
			L -= 1
	do.reverse()
	vertex = 2
	edge = [[1, 2, 0], [1, 2, 1]]
	l = 2
	for op in do:
		if op == '*2':
			edge = [[v1, v2, c * 2] for (v1, v2, c) in edge]
			edge.append([vertex, vertex + 1, 0])
			edge.append([vertex, vertex + 1, 1])
			vertex += 1
			l *= 2
		elif op == '+1':
			edge.append([1, vertex, l])
			l += 1
	ans = '{} {}\n'.format(vertex, len(edge))
	ans += '\n'.join([' '.join(map(str, row)) for row in edge])
	return ans
L = int(input())
print(d_all_your_paths_are_different_lengths(L))


L = int(input())
N = 0
for i in range(21):
	if 2 ** i > L:
		break
	else:
		N = i
N += 1
G = []
for i in range(N - 1):
	G.append((i, i + 1, 0))
	G.append((i, i + 1, 2 ** i))
R = list(range(2 ** (N - 1), L))
marker = 0
B = bin(len(R))[2:][::-1]
for i in range(len(B) - 1, -1, -1):
	if B[i] == '0':
		continue
	G.append((i, N - 1, R[marker]))
	marker += 2 ** i
print(N, len(G))
for (u, v, w) in G:
	print(u + 1, v + 1, w)


l = int(input())
d = l.bit_length()
g = []
for i in range(d - 1):
	g.append((i + 1, i + 2, 0))
	g.append((i + 1, i + 2, 2 ** (d - i - 2)))
s = 1 << d - 1
for i in range(d - 1)[::-1]:
	if 1 << i & l:
		g.append((1, d - i, s))
		s += 1 << i
print(d, len(g))
for (u, v, c) in g:
	print(u, v, c)


import math
L = int(input())
N = int(math.log2(L)) + 1
M = 2 * (N - 1)
edges = []
for i in range(N - 1):
	edges.append('{0} {1} {2}'.format(i + 1, i + 2, 0))
for i in range(N - 1):
	edges.append('{0} {1} {2}'.format(i + 1, i + 2, 2 ** i))
node = L - 2 ** (N - 1)
X = 2 ** (N - 1)
while node > 0:
	M += 1
	t = int(math.log2(node)) + 1
	edges.append('{0} {1} {2}'.format(t, N, X))
	node -= 2 ** (t - 1)
	X += 2 ** (t - 1)
output = '{0} {1}\n{2}'.format(N, M, '\n'.join(edges))
print(output)


L = int(input())
b = format(L, 'b')
n = len(b)
m = 2 * (n - 1) + b.count('1') - 1
print(n, m)
for i in range(1, n):
	print(i, i + 1, 0)
	print(i, i + 1, 2 ** (i - 1))
w = 2 ** (n - 1)
for j in range(20, -1, -1):
	if L - w >> j & 1:
		print(j + 1, n, w)
		w += 2 ** j


L = int(input())
N = L.bit_length()
E = []
for i in range(1, N):
	E.append((i, i + 1, 0))
	E.append((i, i + 1, 2 ** (i - 1)))
s = 2 ** (N - 1)
for i in reversed(range(N - 1)):
	if L >> i & 1:
		E.append((i + 1, N, s))
		s += 2 ** i
print(N, len(E))
for (a, b, c) in E:
	print(a, b, c)


L = int(input())

def digits_count(n):
	cnt = 0
	while n != 0:
		cnt += 1
		n //= 2
	return cnt

def doubling(n, m):
	y = 1
	base = n
	while m != 0:
		if m % 2 == 1:
			y *= base
		base *= base
		m //= 2
	return y
m = digits_count(L)
A = [0 for _ in range(m)]
for i in range(m, 0, -1):
	A[i - 1] = L % 2
	L //= 2
binomial = [1 for _ in range(m)]
for i in range(1, m):
	binomial[i] = binomial[i - 1] * 2
vert = [[i * m + i + 1, binomial[i]] for i in range(m - 1)]
vert = vert[:] + [[i * m + i + 1, 0] for i in range(m - 1)]
S = doubling(2, m - 1)
for i in range(1, m):
	if A[i] == 1:
		vert.append([(m - i - 1) * m + m - 1, S])
		S += binomial[m - i - 1]
print(m, len(vert))
for i in vert:
	print(i[0] // m + 1, i[0] % m + 1, i[1])


L = int(input())
Lbin = bin(L)[2:][::-1]
N = len(Lbin)
M = 2 * (N - 1) + Lbin.count('1') - 1
print(N, M)
for i in range(0, N - 1):
	print(i + 1, i + 2, 0)
	print(i + 1, i + 2, 2 ** i)
weight = L
for i in range(0, N - 1):
	if Lbin[i] == '1':
		weight -= 2 ** i
		print(i + 1, N, weight)


L = int(input())
paths = []
n = 2
v = 1
while n <= L:
	paths.append((v, v + 1, 0))
	paths.append((v, v + 1, n // 2))
	v += 1
	n *= 2
n //= 2
vlast = v
nn = n
ll = L - n
while ll > 0:
	if ll >= n:
		paths.append((v, vlast, nn))
		ll -= n
		nn += n
	n //= 2
	v -= 1
print(vlast, len(paths))
for e in paths:
	print(*e)


L = int(input())
r = L.bit_length() - 1
N = r + 1
graph = []
append = graph.append
for i in range(1, r + 1):
	append([i, i + 1, 0])
	append([i, i + 1, 2 ** (i - 1)])
for t in range(N - 1, 0, -1):
	if L - 2 ** (t - 1) >= 2 ** r:
		append([t, N, L - 2 ** (t - 1)])
		L -= 2 ** (t - 1)
print(N, len(graph))
for g in graph:
	print(*g)


l = int(input())
for i in range(1, 21):
	if 2 ** i > l:
		n = i
		break
m = 2 * (n - 1)
data = []
for i in range(1, n):
	data.append([i, i + 1, 0])
	data.append([i, i + 1, 2 ** (n - i - 1)])
add = 2 ** (n - 1)
for i in range(1, n):
	if l >> n - 1 - i & 1 == 1:
		data.append([1, i + 1, add])
		add += 2 ** (n - 1 - i)
		m += 1
print(str(n) + ' ' + str(m))
for u in data:
	print(*u)


L = int(input())
r = 0
while 2 ** r <= L:
	r += 1
E = []
for i in range(1, r):
	E.append((i, i + 1, 0))
	E.append((i, i + 1, 2 ** (i - 1)))
n = 2 ** (r - 1)
while True:
	d = L - 1 - n + 1
	if d <= 0:
		break
	zi = 0
	while 2 ** zi <= d:
		zi += 1
	E.append((zi, r, n))
	n = n + 2 ** (zi - 1)
print('{} {}'.format(r, len(E)))
for e in E:
	print('{} {} {}'.format(e[0], e[1], e[2]))


from math import log, floor
L = int(input())
n = floor(log(L, 3))
l = [L // 3 ** (n + 1 - i) % 3 for i in range(1, n + 2)]
N = n + 2
uvws = [(i, i + 1, j * 3 ** (n + 1 - i)) for i in range(2, n + 2) for j in range(3)] + [(1, i, j * 3 ** (n + 2 - i) + sum((l[k - 1] * 3 ** (n + 1 - k) for k in range(1, i - 1)))) for i in range(2, n + 3) for j in range(l[i - 2])]
M = len(uvws)
print('{} {}'.format(N, M))
for uvw in uvws:
	print('{} {} {}'.format(*uvw))


import math
L = int(input())
n = int(math.log2(L))
dag = []
for i in range(1, n + 1):
	dag.append(' '.join(map(str, [i, i + 1, 2 ** (i - 1)])))
	dag.append(' '.join(map(str, [i, i + 1, 0])))
for i in range(n, 0, -1):
	if L - 2 ** (i - 1) >= 2 ** n:
		L -= 2 ** (i - 1)
		dag.append(' '.join(map(str, [i, n + 1, L])))
print(n + 1, len(dag))
print('\n'.join(dag))


import sys
sys.setrecursionlimit(10000000)
MOD = 10 ** 9 + 7
INF = 10 ** 15

def main():
	L = int(input())
	edges = []
	vertex = 1
	flag = True
	before = -1
	for i in range(19, -1, -1):
		if L >> i & 1:
			if flag:
				flag = False
				vertex = i + 1
				for j in range(1, vertex):
					edges.append((j, j + 1, 0))
					edges.append((j, j + 1, 1 << j - 1))
				before = 1 << i
			else:
				edges.append((i + 1, vertex, before))
				before += 1 << i
	print(vertex, len(edges))
	for t in edges:
		print(*t)

def __starting_point():
	main()
__starting_point()


L = int(input())
p = 0
ans = []
while L >= 2 ** (p + 1):
	ans.append([p + 1, p + 2, 2 ** p])
	ans.append([p + 1, p + 2, 0])
	p += 1
endN = p + 1
tmp = 2 ** p
L -= tmp
while L != 0:
	p = 0
	while L - 2 ** p >= 0:
		p += 1
	ans.append([p, endN, tmp])
	L -= 2 ** (p - 1)
	tmp += 2 ** (p - 1)
print(endN, len(ans))
for (a, b, c) in ans:
	print(a, b, c)


n = int(input())
t = n
ar = []
while t > 0:
	ar.append(t)
	if t % 2 == 0:
		t = t // 2
	else:
		t -= 1

class Graph:

	def __init__(self):
		self.vertices = set()
		self.edges = []

	def addedge(self, a, b, w):
		self.edges.append([a, b, w])
		self.vertices.add(a)
		self.vertices.add(b)
g = Graph()
g.addedge(0, 1, 0)
g.addedge(0, 1, 1)
for i in range(3, len(ar) + 1):
	if ar[-i] == ar[-i + 1] + 1:
		g.addedge(0, len(g.vertices) - 1, ar[-i] - 1)
	else:
		for j in g.edges:
			j[2] *= 2
		g.addedge(len(g.vertices) - 1, len(g.vertices), 0)
		g.addedge(len(g.vertices) - 2, len(g.vertices) - 1, 1)
print(len(g.vertices), len(g.edges))
for i in g.edges:
	print(i[0] + 1, i[1] + 1, i[2])


import sys
input = sys.stdin.readline
L = int(input())
ans = [[1, 2, 0], [1, 2, 1]]
S = 1
T = 2

def recursion(x):
	global T
	if x == 2:
		return
	if x % 2 == 1:
		recursion(x - 1)
		ans.append([S, T, x - 1])
	else:
		recursion(x // 2)
		for i in range(len(ans)):
			ans[i][2] = 2 * ans[i][2]
		T += 1
		ans.append([T - 1, T, 0])
		ans.append([T - 1, T, 1])
	return
recursion(L)
print(T, len(ans))
for (i, j, k) in ans:
	print(i, j, k)


def main():
	L = int(input())
	r = 0
	while 2 ** (r + 1) <= L:
		r += 1
	assert r < 20
	N = r + 1
	edges = list()
	for i in range(1, N):
		edges.append((i, i + 1, 0))
		edges.append((i, i + 1, 2 ** (i - 1)))
	for t in range(N - 1, 0, -1):
		if L - 2 ** (t - 1) >= 2 ** r:
			edges.append((t, N, L - 2 ** (t - 1)))
			L -= 2 ** (t - 1)
	print('{} {}'.format(N, len(edges)))
	for e in edges:
		print(' '.join(map(str, e)))
main()


from math import log2
L = int(input())
r = int(log2(L))
N = r + 1
edge = []
for i in range(r):
	edge.append((i + 1, i + 2, 2 ** i))
	edge.append((i + 1, i + 2, 0))
for t in range(N - 1, 0, -1):
	s = L - 2 ** (t - 1)
	if s >= 2 ** r:
		edge.append((t, N, s))
		L = s
print(N, len(edge))
for e in edge:
	print(*e)


import sys
sys.setrecursionlimit(100000000)

def input():
	return sys.stdin.readline()[:-1]
from bisect import *
from collections import *
from heapq import *
from math import *
L = int(input())
n = int(log(L, 2))
es = []
m = min(n, 19)
for i in range(1, 20):
	es.append((i, i + 1, 0))
for i in range(m):
	es.append((i + 1, i + 2, 1 << i))
t = L - (1 << m)
for i in range(20):
	if t >> i & 1:
		L -= 1 << i
		es.append((i + 1, 20, L))
print((20, len(es)))
for (u, v, c) in es:
	print((u, v, c))


L = int(input())
B = bin(L)
N = len(B) - 2
Lines = []
for i in range(1, N):
	Lines.append((i, i + 1, 0))
	Lines.append((i, i + 1, 2 ** (i - 1)))
for i in range(N - 1):
	if B[N + 1 - i] == '1':
		Lines.append((i + 1, N, L - 2 ** i))
		L -= 2 ** i
print(N, len(Lines))
for Line in Lines:
	print('{} {} {}'.format(Line[0], Line[1], Line[2]))


def main():
	L = int(input())
	N = 2
	while 2 ** N <= L:
		N += 1
	L -= 2 ** (N - 1)
	E = []
	for i in range(N - 1):
		E.append((N - i - 1, N - i, 0))
		E.append((N - i - 1, N - i, 2 ** i))
	i = 0
	nxt = 2 ** (N - 1)
	for i in range(2, N + 1):
		tmp = 2 ** (N - i)
		if tmp <= L:
			E.append((1, i, nxt))
			L -= tmp
			nxt += tmp
	print(N, len(E))
	for (u, v, w) in E:
		print(u, v, w)
main()


L = int(input())
Edges = []
n = 1
while 2 ** (n - 1) - 1 < L:
	n += 1
n -= 1
for i in range(1, n):
	Edges.append([i, i + 1, 0])
	Edges.append([i, i + 1, 2 ** (i - 1)])
remain = L - 2 ** (n - 1)
for x in range(n - 1, 0, -1):
	if 2 ** (x - 1) <= remain:
		Edges.append([x, n, L - remain])
		remain -= 2 ** (x - 1)
print(n, len(Edges))
for (u, v, w) in Edges:
	print(u, v, w)


import sys

def solve(L: int):
	tmp = L
	a = []
	while tmp > 0:
		a.append(tmp)
		tmp //= 2
	a.reverse()
	e = []
	for i in range(1, len(a)):
		e.append([i, i + 1, 0])
		e.append([i, i + 1, a[i - 1]])
		if a[i] % 2 > 0:
			e.append([1, i + 1, a[i] - 1])
	print(len(a), len(e))
	for t in e:
		print(t[0], t[1], t[2])
	return

def main():

	def iterate_tokens():
		for line in sys.stdin:
			for word in line.split():
				yield word
	tokens = iterate_tokens()
	L = int(next(tokens))
	solve(L)
main()


import sys
input = sys.stdin.readline

def main():
	L = int(input())
	Lstr = bin(L)[2:]
	N = len(Lstr)
	M = (N - 1) * 2 + (Lstr.count('1') - 1)
	print(N, M)
	c = 1
	for i in range(1, N):
		print(i, i + 1, c)
		print(i, i + 1, 0)
		c *= 2
	c = 2 ** (N - 1)
	for (i, v) in enumerate(Lstr[::-1]):
		if i == N - 1:
			continue
		if v == '1':
			print(i + 1, N, c)
			c += 2 ** i
main()


L = int(input())

def decompose(L):
	if L < 2:
		assert L == 1
		return []
	r = L % 2
	return [r] + decompose((L - r) // 2)
dec = decompose(L)
N = len(dec) + 1
edge = []
base = 1
for i in range(len(dec) - 1, -1, -1):
	for w in range(2):
		edge.append((i + 1, i + 2, w * base))
	base *= 2
	for w in range(dec[i]):
		edge.append((i + 1, N, base + w))
	base += dec[i]
M = len(edge)
print(N, M)
for e in edge:
	print(' '.join(map(str, e)))


import os
import sys
if os.getenv('LOCAL'):
	sys.stdin = open('_in.txt', 'r')
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
IINF = 10 ** 18
MOD = 10 ** 9 + 7
L = int(sys.stdin.buffer.readline())
V = L.bit_length()
ans = []
for v in range(V - 1):
	ans.append((v, v + 1, 0))
	ans.append((v, v + 1, 2 ** v))
pos = V - 2
w = 1 << L.bit_length() - 1
while pos >= 0:
	if L & 1 << pos:
		ans.append((pos, V - 1, w))
		w |= L & 1 << pos
	pos -= 1
E = len(ans)
print((V, E))
for r in ans:
	(v, u, w) = r
	v += 1
	u += 1
	print((v, u, w))


import math
L = int(input())
r = int(math.log2(L))
vertex = r + 1
edge = 2 * r
res = []
for i in range(1, r + 1):
	res.append([i, i + 1, 0])
	res.append([i, i + 1, 2 ** (i - 1)])
for i in range(r, 0, -1):
	if L - 2 ** (i - 1) >= 2 ** r:
		L -= 2 ** (i - 1)
		res.append([i, vertex, L])
		edge += 1
print(vertex, edge)
for l in res:
	print(*l)


L = int(input())
N = len(str(bin(L))) - 3
E = []
for n in range(N):
	E.append((n + 1, n + 2, 0))
	E.append((n + 1, n + 2, 2 ** (N - n - 1)))
H = 2 ** N
for (i, c) in enumerate(str(bin(L))[2:]):
	if c == '1' and i:
		E.append((1, i + 1, H))
		H += 2 ** (N - i)
print(N + 1, len(E))
for e in E:
	print(*e)


import math
l = int(input())
r = math.floor(math.log2(l))
num_vertex = 0
num_edge = 0
num_vertex += r + 1
print_list = []
for i in range(r):
	print_list.append([i + 1, i + 2, 0])
	print_list.append([i + 1, i + 2, 2 ** i])
	num_edge += 2
for i in reversed(range(r + 1)):
	if l - 2 ** i >= 2 ** r:
		print_list.append([i + 1, r + 1, l - 2 ** i])
		l -= 2 ** i
		num_edge += 1
print(num_vertex, num_edge)
for i in print_list:
	print(*i)


def main():
	L = int(input())
	b = bin(L)[2:]
	bl = len(b)
	r = []
	for i in range(bl - 1):
		r.append((i + 1, i + 2, 0))
		r.append((i + 1, i + 2, 2 ** i))
	if L == 2 ** (bl - 1):
		pr(r)
		return
	end = bl
	for i in reversed(list(range(1, end))):
		if L - 2 ** (i - 1) >= 2 ** (end - 1):
			r.append((i, end, L - 2 ** (i - 1)))
			L -= 2 ** (i - 1)
	pr(r)

def pr(r):
	m = 0
	for i in r:
		m = max(m, i[1])
	print((m, len(r)))
	for i in r:
		print((i[0], i[1], i[2]))
main()


import sys
from math import *
from itertools import *
from collections import *
from functools import *
try:
	from math import gcd
except Exception:
	from fractions import gcd

def solve(L: int):
	r = 0
	while 2 ** r <= L:
		r += 1
	r -= 1
	edges = []
	nodes = list(range(1, r + 2))
	for (s, d) in zip(nodes, nodes[1:]):
		edges.append((s, d, 0))
		edges.append((s, d, 2 ** (s - 1)))
	base = 2 ** r
	for n in list(reversed(nodes))[1:]:
		c = 2 ** (n - 1)
		if base <= L - c:
			edges.append((n, nodes[-1], L - c))
			L -= c
	ret = ['{} {}'.format(r + 1, len(edges))] + ['{} {} {}'.format(s, d, c) for (s, d, c) in edges]
	return '\n'.join(ret)

def main():

	def iterate_tokens():
		for line in sys.stdin:
			for word in line.split():
				yield word
	tokens = iterate_tokens()
	L = int(next(tokens))
	result = solve(L)
	print(result)
main()


import sys
import math
from collections import defaultdict
sys.setrecursionlimit(10 ** 7)

def input():
	return sys.stdin.readline()[:-1]
mod = 10 ** 9 + 7

def I():
	return int(input())

def II():
	return map(int, input().split())

def III():
	return list(map(int, input().split()))

def Line(N):
	read_all = [tuple(map(int, input().split())) for _ in range(N)]
	return map(list, zip(*read_all))
L = I()
N = math.floor(math.log2(L)) + 1
M = 0
edge = []
for i in range(N - 1):
	edge.append([i, i + 1, 0])
	edge.append([i, i + 1, 2 ** i])
	M += 2
for i in range(N - 1)[::-1]:
	if L - 2 ** i >= 2 ** (N - 1):
		edge.append([i, N - 1, L - 2 ** i])
		M += 1
		L -= 2 ** i
print(N, M)
for e in edge:
	print(e[0] + 1, e[1] + 1, e[2])


L = int(input())
b = bin(L - 1)[2:]
l = len(b)
out = []
for i in range(1, l + 1):
	out.append([i, i + 1, 0])
for i in range(2, l + 1):
	out.append([i, i + 1, 1 << l - i])
if not '0' in b:
	out.append([1, 2, 1 << l - 1])
	b = ''
while len(b) > 0 and b != '0':
	if b[-1] == '0':
		out.append([1, len(b) + 1, int((b + '0' * l)[:l], 2)])
		b = bin(int(b, 2) - 1)[2:]
	b = b[:-1]
if l < 20:
	print(l + 1, len(out))
	for sub in out:
		print(' '.join(map(str, sub)))
else:
	print(l, len(out) - 1)
	for (u, v, w) in out[1:]:
		u = max(1, u - 1)
		v = max(1, v - 1)
		print(u, v, w)


L = int(input())
N = 0
A = []
ret = []
while True:
	N += 1
	A.append(L % 2)
	L //= 2
	if L < 1:
		break
s = 2
l = 1
M = 0
for i in range(len(A) - 2, -1, -1):
	ret.append('{0} {1} {2}'.format(s - 1, s, l))
	ret.append('{0} {1} {2}'.format(s - 1, s, 0))
	M += 2
	if A[i] == 1:
		l *= 2
		ret.append('{0} {1} {2}'.format(1, s, l))
		l += 1
		M += 1
	else:
		l *= 2
	s += 1
print('{0} {1}'.format(N, M))
for r in ret:
	print(r)


l = int(input())
r = len(bin(l)[2:]) - 1
w = 2 ** r
outlist = []
for t in range(r, 0, -1):
	if l - 2 ** r >= 2 ** (t - 1):
		outlist.append('{} {} {}'.format(t, r + 1, w))
		w += 2 ** (t - 1)
		l = l - 2 ** (t - 1)
print(r + 1, len(outlist) + 2 * r)
for i in range(1, r + 1):
	print('{} {} 0'.format(i, i + 1))
	print('{} {} {}'.format(i, i + 1, 2 ** (i - 1)))
for j in outlist:
	print(j)


L = int(input())
N = len(str(bin(L))) - 2
bitL = [0] * 20
splitL = [0] * 20
sumL = [0] * 20
for i in range(19, -1, -1):
	if L % 2 == 1:
		bitL[i] = 1
	L = L // 2
for i in range(19, -1, -1):
	splitL[i] = int(bitL[i]) * 2 ** (19 - i)
for i in range(20):
	if i == 0:
		sumL[i] = splitL[i]
	else:
		sumL[i] = splitL[i] + sumL[i - 1]
edge = []
for i in range(N - 1):
	edge.append([i + 1, i + 2, 0])
	edge.append([i + 1, i + 2, 2 ** i])
for i in range(21 - N, 20):
	if bitL[i] == 1:
		edge.append([20 - i, N, sumL[i - 1]])
print(N, len(edge))
for i in range(len(edge)):
	print(edge[i][0], edge[i][1], edge[i][2])


L = int(input())
l = L
r = 1
nodes = 1
bits = 0
while l != 1:
	bits += l & 1
	l >>= 1
	r <<= 1
	nodes += 1
print(str(nodes) + ' ' + str((nodes - 1) * 2 + bits))
for i in range(1, nodes):
	r >>= 1
	print(str(i) + ' ' + str(i + 1) + ' ' + str(0))
	print(str(i) + ' ' + str(i + 1) + ' ' + str(r))
r = 1 << nodes - 1
d = r
for i in range(1, nodes):
	if r >> i & L:
		print(str(1) + ' ' + str(i + 1) + ' ' + str(d))
		d += r >> i


L = int(input())
ans = []
N = len(bin(L)[2:])
for i in range(N - 1)[::-1]:
	ans.append([i + 1, i + 2, 2 ** (N - i - 2)])
	ans.append([i + 1, i + 2, 0])
need = L - 2 ** (N - 1)
cost = list(range(2 ** (N - 1), 2 ** (N - 1) + need))
marker = 0
bit = bin(need)[2:][::-1]
for i in range(len(bit)):
	if bit[i] != '1':
		continue
	ans.append([1, N - i, cost[marker]])
	marker += 2 ** i
print(N, len(ans))
for a in ans:
	print(' '.join(map(str, a)))


L = int(input())
v = 1
edges = []
n = 2
cost = 1
while n <= L:
	edges.append((v, v + 1, 0))
	edges.append((v, v + 1, cost))
	cost *= 2
	v += 1
	n *= 2
goal = v
n //= 2
N = n
L -= N
while L > 0:
	if L >= n:
		edges.append((v, goal, N))
		L -= n
		N += n
	n //= 2
	v -= 1
print(goal, len(edges))
for e in edges:
	print(*e)


import math
l = int(input())
n = int(math.log2(l)) + 1
g = []
for i in range(1, n):
	g.append([i, i + 1, 2 ** (n - i - 1)])
	g.append([i, i + 1, 0])
s = 2 ** (n - 1)
while l > s:
	t = n - int(math.log2(l - s))
	g.append([1, t, s])
	s += 2 ** int(math.log2(l - s))
print(n, len(g))
for i in range(0, len(g)):
	print(' '.join(list(map(str, g[i]))))


import sys
sr = lambda : sys.stdin.readline().rstrip()
ir = lambda : int(sr())
lr = lambda : list(map(int, sr().split()))
L = ir()
length = L.bit_length()
edges = []
for i in range(1, length):
	edges.append((i, i + 1, 0))
	edges.append((i, i + 1, 2 ** (i - 1)))
for i in range(length - 1):
	if L >> i & 1:
		L -= 2 ** i
		edges.append((i + 1, length, L))
print(length, len(edges))
for e in edges:
	print(*e)


def gen_graph(i, step, L):
	if L == 1:
		return ([i], [])
	(v, e) = gen_graph(i + 1, 2 * step, L // 2)
	v = [i] + v
	e = e + [(i, i + 1, 0), (i, i + 1, step)]
	if L % 2 == 0:
		return (v, e)
	e.append((i, v[-1], step * (L - 1)))
	return (v, e)
L = int(input())
(v, e) = gen_graph(1, 1, L)
print(len(v), len(e))
for (a, b, c) in e:
	print(a, b, c)


L = int(input())
N = L.bit_length()
ans = []
for i in range(N - 1):
	ans.append((i, i + 1, 0))
	ans.append((i, i + 1, 2 ** (N - i - 2)))
X = L - 2 ** (N - 1)
dist = 2 ** (N - 1)
for i in reversed(list(range(X.bit_length()))):
	if X & 1 << i:
		ans.append((0, N - i - 1, dist))
		dist += 2 ** i
print((N, len(ans)))
for (a, b, d) in ans:
	print((a + 1, b + 1, d))


import math
L = int(input())
n = int(math.log2(L))
N = n + 1
edges = []
for i in range(1, N):
	edges.append((i, i + 1, 0))
	edges.append((i, i + 1, 2 ** (n - i)))
res = L - 2 ** n
bits = format(res, '0' + str(n) + 'b')
weight = 2 ** n
for (i, bit) in enumerate(bits):
	if int(bit):
		edges.append((1, i + 2, weight))
		weight += 2 ** (n - i - 1)
print(N, len(edges))
for row in edges:
	print(*row)


n = int(input())
ans = []
count = 1
two = 1
for i in range(20):
	if two * 2 <= n:
		count += 1
		ans.append([count - 1, count, 0])
		ans.append([count - 1, count, two])
		two *= 2
	else:
		break
for i in range(count, 0, -1):
	if n - pow(2, i - 1) >= two:
		ans.append([i, count, n - pow(2, i - 1)])
		n -= pow(2, i - 1)
print(count, len(ans))
for i in ans:
	print(*i)


from sys import stdout
from bisect import bisect_left as binl
from copy import copy, deepcopy
mod = 1

def intin():
	input_tuple = input().split()
	if len(input_tuple) <= 1:
		return int(input_tuple[0])
	return tuple(map(int, input_tuple))

def intina():
	return [int(i) for i in input().split()]

def intinl(count):
	return [intin() for _ in range(count)]

def modadd(x, y):
	global mod
	return (x + y) % mod

def modmlt(x, y):
	global mod
	return x * y % mod

def lcm(x, y):
	while y != 0:
		z = x % y
		x = y
		y = z
	return x

def combination(x, y):
	assert x >= y
	if y > x // 2:
		y = x - y
	ret = 1
	for i in range(0, y):
		j = x - i
		i = i + 1
		ret = ret * j
		ret = ret // i
	return ret

def get_divisors(x):
	retlist = []
	for i in range(1, int(x ** 0.5) + 3):
		if x % i == 0:
			retlist.append(i)
			retlist.append(x // i)
	return retlist

def get_factors(x):
	retlist = []
	for i in range(2, int(x ** 0.5) + 3):
		while x % i == 0:
			retlist.append(i)
			x = x // i
	retlist.append(x)
	return retlist

def make_linklist(xylist):
	linklist = {}
	for (a, b) in xylist:
		linklist.setdefault(a, [])
		linklist.setdefault(b, [])
		linklist[a].append(b)
		linklist[b].append(a)
	return linklist

def calc_longest_distance(linklist, v=1):
	distance_list = {}
	distance_count = 0
	distance = 0
	vlist_previous = []
	vlist = [v]
	nodecount = len(linklist)
	while distance_count < nodecount:
		vlist_next = []
		for v in vlist:
			distance_list[v] = distance
			distance_count += 1
			vlist_next.extend(linklist[v])
		distance += 1
		vlist_to_del = vlist_previous
		vlist_previous = vlist
		vlist = list(set(vlist_next) - set(vlist_to_del))
	max_distance = -1
	max_v = None
	for (v, distance) in distance_list.items():
		if distance > max_distance:
			max_distance = distance
			max_v = v
	return (max_distance, max_v)

def calc_tree_diameter(linklist, v=1):
	(_, u) = calc_longest_distance(linklist, v)
	(distance, _) = calc_longest_distance(linklist, u)
	return distance

def main():
	L = intin()
	r = 0
	while True:
		if 2 ** (r + 1) > L:
			break
		r += 1
	n = r + 1
	path_list = []
	path_list.extend([(i + 1, i + 2, 0) for i in range(r)])
	path_list.extend([(i + 1, i + 2, 2 ** i) for i in range(r)])
	remain = L - 2 ** r
	next = 2 ** r
	for i in reversed(list(range(r))):
		if remain >= 2 ** i:
			path_list.append((i + 1, n, next))
			remain -= 2 ** i
			next += 2 ** i
	print('%d %d' % (n, len(path_list)))
	for path in path_list:
		print('%d %d %d' % path)
main()


import math
L = int(input())
N = math.floor(math.log2(L)) + 1
edge = []
for i in range(N - 1):
	edge.append((i + 1, i + 2, 0))
	edge.append((i + 1, i + 2, 1 << i))
for i in range(N - 1, 0, -1):
	if L - (1 << i - 1) >= 2 ** (N - 1):
		edge.append((i, N, L - (1 << i - 1)))
		L -= 1 << i - 1
print(N, len(edge))
for e in edge:
	print(str(e).lstrip('(').rstrip(')').replace(',', ''))


l = int(input())
for i in range(21):
	if 2 ** i > l:
		n = i
		break
m = (n - 1) * 2
s = l - 2 ** (n - 1)
value = 2 ** (n - 1)
path_add = [0 for i in range(n - 1)]
path_add_value = [0 for i in range(n - 1)]
for i in range(n - 1):
	if s >= 2 ** (n - 2 - i):
		s -= 2 ** (n - 2 - i)
		path_add[-(i + 1)] = 1
		path_add_value[-(i + 1)] = value
		value += 2 ** (n - 2 - i)
print(n, m + sum(path_add))
for i in range(n - 1):
	print(i + 1, i + 2, 0)
	print(i + 1, i + 2, 2 ** i)
for i in range(n - 1):
	if path_add[i] == 1:
		print(i + 1, n, path_add_value[i])


from collections import defaultdict, Counter
from itertools import product, groupby, count, permutations, combinations
from math import pi, sqrt
from collections import deque
from bisect import bisect, bisect_left, bisect_right
from string import ascii_lowercase
from functools import lru_cache
import sys
sys.setrecursionlimit(10000)
INF = float('inf')
(YES, Yes, yes, NO, No, no) = ('YES', 'Yes', 'yes', 'NO', 'No', 'no')
(dy4, dx4) = ([0, 1, 0, -1], [1, 0, -1, 0])
(dy8, dx8) = ([0, -1, 0, 1, 1, -1, -1, 1], [1, 0, -1, 0, 1, 1, -1, -1])

def inside(y, x, H, W):
	return 0 <= y < H and 0 <= x < W

def ceil(a, b):
	return (a + b - 1) // b

def main():
	L = int(input())
	m = []
	while L > 1:
		if L % 2 == 0:
			m.append(0)
			L //= 2
		else:
			m.append(1)
			L -= 1
	ans = []
	last = 1
	l = 1
	for x in m[::-1]:
		if x == 0:
			for i in range(len(ans)):
				ans[i][2] *= 2
			ans.append([last, last + 1, 0])
			ans.append([last, last + 1, 1])
			last += 1
			l *= 2
		else:
			ans.append([1, last, l])
			l += 1
	print(last, len(ans))
	for x in ans:
		print(*x)
main()


L = int(input())
n = len(str(bin(L))) - 3
e = []
h = 2 ** n
for i in range(1, n + 1):
	e += [(i, i + 1, 0), (i, i + 1, 2 ** (n - i))]
	if 2 ** (n - i) & L:
		e += [(1, i + 1, h)]
		h += 2 ** (n - i)
print(n + 1, len(e))
for v in e:
	print(*v)


import sys
import math
input_methods = ['clipboard', 'file', 'key']
using_method = 1
input_method = input_methods[using_method]
tin = lambda : map(int, input().split())
lin = lambda : list(IN())
mod = 1000000007

def main():
	L = int(input())
	v = int(math.log2(L))
	num_p = v
	path_info = []
	for i in range(v):
		path_info.append([i, i + 1, 0])
		path_info.append([i, i + 1, 2 ** i])
	nokori = L - 2 ** v
	for i in range(v + 1):
		m = v - i
		if 2 ** m <= nokori:
			path_info.append([m, v, L - nokori])
			nokori -= 2 ** m
	print(v + 1, len(path_info))
	for l in path_info:
		(f, t, w) = l
		print(*[f + 1, t + 1, w])
isTest = False

def pa(v):
	if isTest:
		print(v)

def input_clipboard():
	import clipboard
	input_text = clipboard.get()
	input_l = input_text.splitlines()
	for l in input_l:
		yield l

def __starting_point():
	if sys.platform == 'ios':
		if input_method == input_methods[0]:
			ic = input_clipboard()
			input = lambda : ic.__next__()
		elif input_method == input_methods[1]:
			sys.stdin = open('inputFile.txt')
		else:
			pass
		isTest = True
	else:
		pass
	ret = main()
	if ret is not None:
		print(ret)
__starting_point()


L = int(input())
ans = []
for i in range(1, 19):
	ans.append((i, i + 1, 0))
	ans.append((i, i + 1, 2 ** (i - 1)))
cur = 0
flag = True
for i in range(20)[::-1]:
	if L >> i & 1:
		if flag:
			for _ in range(2):
				ans.append((i, 20, cur))
				cur += 1 << i - 1
		else:
			ans.append((i + 1, 20, cur))
			cur += 1 << i
	else:
		flag = False
print(20, len(ans))
for tpl in ans:
	print(*tpl)


def main():
	L = int(input())
	n = 1
	while 2 ** n <= L:
		n += 1
	n -= 1
	ans = []
	for i in range(1, n + 1):
		ans.append([i, i + 1, 0])
		ans.append([i, i + 1, 2 ** (i - 1)])
	for i in reversed(range(1, n + 1)):
		if L - 2 ** (i - 1) >= 2 ** n:
			ans.append([i, n + 1, L - 2 ** (i - 1)])
			L -= 2 ** (i - 1)
	print(n + 1, len(ans))
	for (u, v, w) in ans:
		print(u, v, w)
main()


L = int(input())
for i in range(21):
	if 2 ** i > L:
		r = i - 1
		break
N = r + 1
ans = []
for i in range(1, N):
	ans.append([str(i), str(i + 1), str(2 ** (i - 1))])
	ans.append([str(i), str(i + 1), str(0)])
t = N - 1
while t >= 1:
	if L - 2 ** (t - 1) >= 2 ** r:
		ans.append([str(t), str(N), str(L - 2 ** (t - 1))])
		L -= 2 ** (t - 1)
	t -= 1
print(N, len(ans))
for i in range(len(ans)):
	print(' '.join(ans[i]))


import sys
from math import ceil

def input():
	return sys.stdin.readline().strip()

def main():
	L = int(input())
	N = 2
	M = 2
	even = 0
	order = [L]
	while L != 2:
		if L % 2 == 0:
			N += 1
			M += 2
			L //= 2
			even += 1
		else:
			M += 1
			L -= 1
		order.append(L)
	print('{} {}'.format(N, M))
	order.pop()
	print('{} {} {}'.format(1, 2, 0))
	print('{} {} {}'.format(1, 2, 2 ** even))
	edge = 2
	while order:
		L = order.pop()
		if L % 2 == 0:
			even -= 1
			print('{} {} {}'.format(edge, edge + 1, 0))
			print('{} {} {}'.format(edge, edge + 1, 2 ** even))
			edge += 1
		else:
			print('{} {} {}'.format(1, edge, (L - 1) * 2 ** even))
main()


l = int(input())
n = 1
ll = l
while ll > 1:
	n += 1
	ll = ll // 2
s = 1
e = []
while l > 1:
	h = l // 2
	e.append((s, s + 1, 0))
	e.append((s, s + 1, h))
	if l > h * 2:
		e.append((s, n, l - 1))
	l = h
	s += 1
print(n, len(e))
for (x, y, w) in e:
	print(x, y, w)


l = int(input())
n = len(bin(l)) - 3
tmp = 2 ** n
print(n + 1, 2 * n + bin(l)[3:].count('1'))
for i in range(n):
	print(i + 1, i + 2, 0)
	print(i + 1, i + 2, 2 ** i)
	if l & 1 << i:
		print(i + 1, n + 1, tmp)
		tmp += 2 ** i


from collections import defaultdict
from collections import deque
from heapq import heappush, heappop
import sys
import math
import bisect
import random
import itertools
sys.setrecursionlimit(10 ** 5)
stdin = sys.stdin

def LI():
	return list(map(int, stdin.readline().split()))

def LF():
	return list(map(float, stdin.readline().split()))

def LI_():
	return list(map(lambda x: int(x) - 1, stdin.readline().split()))

def II():
	return int(stdin.readline())

def IF():
	return float(stdin.readline())

def LS():
	return list(map(list, stdin.readline().split()))

def S():
	return list(stdin.readline().rstrip())

def IR(n):
	return [II() for _ in range(n)]

def LIR(n):
	return [LI() for _ in range(n)]

def FR(n):
	return [IF() for _ in range(n)]

def LFR(n):
	return [LI() for _ in range(n)]

def LIR_(n):
	return [LI_() for _ in range(n)]

def SR(n):
	return [S() for _ in range(n)]

def LSR(n):
	return [LS() for _ in range(n)]
mod = 1000000007

def A():
	n = II()
	a = n // 2
	b = n - a
	print(a * b)
	return

def B():
	(x1, y1, x2, y2) = LI()
	a = x2 - x1
	b = y2 - y1
	print(x2 - b, y2 + a, x1 - b, y1 + a)
	return

def C():
	(n, k) = LI()
	if k % 2:
		print((n // k) ** 3)
	else:
		print(int((n // k) ** 3 + ((n - k / 2) // k + 1) ** 3))
	return

def D():
	l = II()
	lBit = bin(l)[:1:-1]
	n = len(lBit)
	ans = []
	for i in range(1, n):
		ans += [(i, i + 1, 0)] + [(i, i + 1, 1 << i - 1)]
	b = 1 << n - 1
	for i in range(n - 1):
		if lBit[-2 - i] == '1':
			ans += [(n - i - 1, n, b)]
			b += 1 << n - i - 2
	print(n, len(ans))
	for a in ans:
		print(*a)
	return
D()


L = int(input())
edges = []
v = base = 1
while base * 2 <= L:
	edges.append([v, v + 1, 0])
	edges.append([v, v + 1, base])
	base *= 2
	v += 1
end = edges[-1][1]
rest = L - base
for i in range(18, -1, -1):
	num = 2 ** i
	if rest >= num:
		edges.append([i + 1, end, L - rest])
		rest -= num
print(v, len(edges))
for i in range(len(edges)):
	print(*edges[i])


from math import log, floor
L = int(input())
N = floor(log(L, 2)) + 1
edge = []
for i in range(1, N):
	edge.append((i, i + 1, 0))
for i in range(1, N):
	edge.append((i, i + 1, 2 ** (i - 1)))
X = 2 ** (N - 1)
while L > X:
	r = floor(log(L - X, 2))
	edge.append((r + 1, N, X))
	X += 2 ** r
M = len(edge)
print(N, M)
for e in edge:
	print(' '.join(map(str, e)))


from math import log2
L = int(input())
ans = []
i = 1
while True:
	if 2 ** i > L:
		last = i
		break
	ans.append([i, i + 1, 2 ** (i - 1)])
	ans.append([i, i + 1, 0])
	i += 1
num = 2 ** (last - 1)
a = L - num
while a > 0:
	ans.append([int(log2(a)) + 1, last, num])
	num += 2 ** int(log2(a))
	a = L - num
print(last, len(ans))
for i in ans:
	print(*i)


L = int(input())
num = 2
start = 1
end = 2
path = [[1, 2, 0], [1, 2, 1]]
func = []

def plus1(s, t, n):
	global num
	path.append([s, t, n])
	num += 1

def times2(s, t, n):
	global end, num
	for edge in path:
		edge[2] *= 2
	path.append([t, t + 1, 0])
	path.append([t, t + 1, 1])
	end += 1
	num *= 2
while L > 2:
	if L % 2 == 1:
		func.append(plus1)
		L -= 1
	else:
		func.append(times2)
		L //= 2
func.reverse()
for f in func:
	f(start, end, num)
print(end, len(path))
for (u, v, w) in path:
	print(u, v, w)


L = int(input())
print(L.bit_length(), 2 * (L.bit_length() - 1) + bin(L)[3:].count('1'))
for i in range(L.bit_length() - 1, 0, -1):
	print(i, i + 1, 0)
	print(i, i + 1, 1 << i - 1)
	if L >> i - 1 & 1:
		print(i, L.bit_length(), L >> i << i)


l = int(input())
r = 0
while 2 ** (r + 1) <= l:
	r += 1
n = r + 1
ans = []
for i in range(r):
	ans.append((i + 1, i + 2, 0))
	ans.append((i + 1, i + 2, 2 ** i))
for t in range(n - 1, 0, -1):
	if l - 2 ** (t - 1) >= 2 ** r:
		ans.append((t, n, l - 2 ** (t - 1)))
		l -= 2 ** (t - 1)
print(n, len(ans))
for a in ans:
	print(*a)


import math
l = int(input())
n = math.floor(math.log2(l)) + 1
e = []
for v in range(n - 1):
	e.append([v + 1, v + 2, 0])
	e.append([v + 1, v + 2, 2 ** v])
	if l >> v & 1:
		e.append([v + 1, n, l - 2 ** v])
		l -= 2 ** v
print(n, len(e))
for x in e:
	print(' '.join(map(str, x)))


import array
from bisect import *
from collections import *
import fractions
import heapq
from itertools import *
import math
import random
import re
import string
import sys
L = int(input())
v = 1
edges = []
n = 2
cost = 1
while n <= L:
	edges.append((v, v + 1, 0))
	edges.append((v, v + 1, cost))
	cost *= 2
	v += 1
	n *= 2
v_sink = v
n //= 2
N = n
L -= N
while L > 0:
	if L >= n:
		edges.append((v, v_sink, N))
		L -= n
		N += n
	n //= 2
	v -= 1
print(v_sink, len(edges))
for e in edges:
	print(*e)


L = int(input())
N = len(bin(L)[2:])
R = 1 << N - 1
UVW = sum([[(i, i + 1, 0), (i, i + 1, 1 << i - 1)] for i in range(1, N)], [])
for (i, s) in enumerate(bin(L)[:2:-1], 1):
	if s == '1':
		UVW.append((i, N, R))
		R += 1 << i - 1
print(N, len(UVW))
for t in UVW:
	print(*t)


def main():
	L = int(input())
	N = 0
	e = []
	d = L
	k = 0
	while 0 < d:
		d = int(d / 2)
		k += 1
		if 2 <= k:
			e.append((k - 1, k, 0))
			e.append((k - 1, k, 2 ** (k - 2)))
	N = k
	d = L
	k = 0
	s = []
	while 1 < d:
		(d, m) = (int(d / 2), d % 2)
		if m == 1:
			s.append(k)
		k += 1
	a = 2 ** (N - 1)
	for i in range(len(s) - 1, -1, -1):
		k = s[i]
		e.append((k + 1, N, a))
		a += 2 ** k
	print('{} {}'.format(N, len(e)))
	for v in e:
		print('{} {} {}'.format(v[0], v[1], v[2]))
main()


L = int(input())
N = L.bit_length()
res = []
for i in range(N - 1):
	res.append((i + 1, i + 2, 1 << i))
	res.append((i + 1, i + 2, 0))
n = 1 << i + 1
m = L - n
for i in reversed(range(m.bit_length())):
	if m >> i & 1:
		m %= 1 << i
		res.append((i + 1, N, n))
		n += 1 << i
print(N, len(res))
for i in range(len(res)):
	print(*res[i])


from math import log2, floor
L = int(input())
ans = []
r = floor(log2(L))
for i in range(r):
	ans.append('{} {} {}'.format(i + 1, i + 2, 0))
	ans.append('{} {} {}'.format(i + 1, i + 2, 2 ** i))
for t in range(r - 1, -1, -1):
	if 2 ** r <= L - 2 ** t:
		ans.append('{} {} {}'.format(t + 1, r + 1, L - 2 ** t))
		L -= 2 ** t
print('{} {}'.format(r + 1, len(ans)))
for s in ans:
	print(s)


L = int(input())
n = L.bit_length()
if L == 2 ** n:
	n += 1
path = []
for i in range(1, n):
	path.append([i, i + 1, 0])
	path.append([i, i + 1, 2 ** (i - 1)])
k = L - 1 - (2 ** (n - 1) - 1)
cur = 2 ** (n - 1)
while k > 0:
	if k == 1:
		kk = 1
	else:
		kk = k.bit_length()
	path.append([kk, n, cur])
	cur += 2 ** (kk - 1)
	k = L - cur
print(n, len(path))
for p in path:
	print(*p)


l = int(input())
s = bin(l)[2:]
n = len(s)
m = 0
ans = []
for i in range(n - 1):
	ans.append([i + 1, i + 2, 0])
	ans.append([i + 1, i + 2, 2 ** (n - 2 - i)])
	m += 2
imp = 2 ** (n - 1)
for i in range(n - 1, 0, -1):
	if s[i] == '1':
		ans.append([1, i + 1, imp])
		m += 1
		imp += 2 ** (n - 1 - i)
print(n, m)
for x in ans:
	print(' '.join(list(map(str, x))))


l = int(input())
b = bin(l)[2:][::-1]
l = []
for i in range(len(b)):
	if b[i] == '1':
		l.append(i)
k = l.pop()
nodes = [i for i in range(1, k + 2)]
edges = []
for i in range(len(nodes) - 1):
	edges.append([nodes[i], nodes[i + 1], 2 ** (k - i - 1)])
	edges.append([nodes[i], nodes[i + 1], 0])
covered = 2 ** k - 1
for x in l:
	edges.append([1, k + 1 - x, covered + 1])
	covered = edges[-1][-1] + 2 ** x - 1
print(max(nodes), len(edges))
for (u, v, w) in edges:
	print(u, v, w)


L = int(input())
edges = []
p2 = 1
N = 1
while L >= p2 * 2:
	N += 1
	p2 *= 2
	edges.append((N - 1, N, 0))
	edges.append((N - 1, N, 2 ** (N - 2)))
rest = L - p2
tmp = p2
for i in range(N, -1, -1):
	if rest >> i & 1:
		edges.append((i + 1, N, tmp))
		tmp += 2 ** i
M = len(edges)
print(N, M)
for edge in edges:
	print(*edge)


l = int(input())
ll = l
l3 = []
while True:
	if ll // 3 == 0:
		l3.append(ll)
		break
	else:
		l3.append(ll % 3)
		ll = ll // 3
N = len(l3) + 1
edge = []
for i in range(1, len(l3)):
	edge.append([i, i + 1, 0])
	edge.append([i, i + 1, 1 * 3 ** (i - 1)])
	edge.append([i, i + 1, 2 * 3 ** (i - 1)])
a = 0
for i in range(len(l3)):
	for j in range(l3[i]):
		edge.append([i + 1, N, j * 3 ** i + a])
	a += l3[i] * 3 ** i
print(N, len(edge))
for i in edge:
	print(i[0], i[1], i[2])


l = int(input())
p = 0
while True:
	if 2 ** p > l:
		p -= 1
		break
	else:
		p += 1
n = p + 1
m = 2 * p
ans = []
for i in range(1, n):
	ans.append([i, i + 1, 0])
	ans.append([i, i + 1, 2 ** (i - 1)])
while l > 2 ** p:
	for i in range(n - 1, 0, -1):
		if l - 2 ** (i - 1) >= 2 ** p:
			ans.append([i, n, l - 2 ** (i - 1)])
			l = l - 2 ** (i - 1)
			m += 1
			break
print(n, m)
for a in ans:
	print(' '.join(list(map(str, a))))


from collections import deque
L = int(input())
Lbin = bin(L)[2:][::-1]
N = len(Lbin)
M = 0
E = deque()
for i in range(0, N - 1):
	E.append(((i + 1, i + 2), 0))
	E.append(((i + 1, i + 2), 2 ** i))
	M += 2
weight = L
for i in range(0, N - 1):
	if Lbin[i] == '1':
		weight -= 2 ** i
		E.append(((i + 1, N), weight))
		M += 1
print((N, M))
for e in E:
	print((e[0][0], e[0][1], e[1]))


import numpy as np
L = int(input())
branches = []
node_count = int(np.log2(L)) + 1
for n in range(node_count - 1):
	branches.append((n, n + 1, 0))
	branches.append((n, n + 1, 2 ** n))
byte_list = list(reversed(format(L, 'b')))[:-1]
a = 2 ** (node_count - 1)
for i in reversed(list(range(len(byte_list)))):
	if byte_list[i] == '1':
		branches.append((i, node_count - 1, a))
		a += 2 ** i
print((node_count, len(branches)))
for (u, v, w) in branches:
	print((u + 1, v + 1, w))


from collections import defaultdict, deque
from heapq import heappush, heappop
import sys
import math
import bisect
import random

def LI():
	return [int(x) for x in sys.stdin.readline().split()]

def I():
	return int(sys.stdin.readline())

def LS():
	return [list(x) for x in sys.stdin.readline().split()]

def S():
	return list(sys.stdin.readline())[:-1]

def IR(n):
	return [I() for i in range(n)]

def LIR(n):
	return [LI() for i in range(n)]

def SR(n):
	return [S() for i in range(n)]

def LSR(n):
	return [LS() for i in range(n)]
sys.setrecursionlimit(1000000)
mod = 1000000007

def A():
	return

def B():
	return

def C():
	return

def D():
	l = I()
	l = list(map(int, bin(l)[2:]))
	n = len(l)
	ans = []
	for i in range(n - 1):
		ans.append((i + 1, i + 2, 0))
		ans.append((i + 1, i + 2, 1 << i))
	w = 1 << n - 1
	for i in range(1, n):
		if l[i]:
			x = n - i
			ans.append((x, n, w))
			w += 1 << x - 1
	print(n, len(ans))
	for (x, y, w) in ans:
		print(x, y, w)
	return

def E():
	return

def F():
	return

def G():
	return

def H():
	return
D()


L = int(input())
l = 0
pp = 0
tmp = L
while tmp > 0:
	l += 1
	pp += tmp % 2
	tmp //= 2
print(l, l * 2 - 3 + pp)
for i in range(1, l):
	print(i, i + 1, 0)
	a = 1 << i - 1
	print(i, i + 1, a)
	if L & a:
		L -= a
		print(i, l, L)


from math import log2
n = int(input())
(r, ans) = (int(log2(n)), [])
for i in range(1, r + 1):
	ans.append([i, i + 1, 2 ** (i - 1)])
for i in range(r, 0, -1):
	if n - 2 ** (i - 1) >= 2 ** r:
		ans.append([i, r + 1, n - 2 ** (i - 1)])
		n -= 2 ** (i - 1)
print(r + 1, len(ans) + r)
for i in range(1, r + 1):
	print(i, i + 1, 0)
for (i, j, k) in ans:
	print(i, j, k)


from itertools import accumulate
L = int(input())
p2 = [2 ** i for i in range(20)]
p2acc = list(accumulate(p2))
for i in range(19, -1, -1):
	if L >= p2[i]:
		N = i + 1
		break
ans = []
for i in range(N - 1):
	ans.append((i, i + 1, 0))
	ans.append((i, i + 1, 2 ** i))
remain = L - 2 ** (N - 1)
bypass = 2 ** (N - 1)
while remain:
	for i in range(19, -1, -1):
		if remain >= p2[i]:
			ans.append((i, N - 1, bypass))
			remain -= p2[i]
			bypass += p2acc[i - 1] + 1
print(N, len(ans))
for (u, v, w) in ans:
	print(u + 1, v + 1, w)


L = int(input())
N = L.bit_length()
res = []
for i in range(N - 1):
	res.append((i + 1, i + 2, 0))
	res.append((i + 1, i + 2, 2 ** i))
rem = L - 2 ** (N - 1)
k = 2 ** (N - 1)
for i in range(rem.bit_length())[::-1]:
	if rem >> i & 1:
		res.append((i + 1, N, k))
		k += 2 ** i
print(N, len(res))
for r in res:
	print(*r)


L = int(input())
keta = 0
while 2 ** keta - 1 < L:
	keta += 1
edge = []
tmp = 1
for i in range(0, keta - 1):
	edge.append('{} {} 0'.format(keta - 1 - i, keta - i))
	edge.append('{} {} {}'.format(keta - 1 - i, keta - i, tmp))
	tmp *= 2
	if L & 1 << keta - 2 - i:
		edge.append('{} {} {}'.format(keta - 1 - i, keta, tmp))
		tmp += 1
if L == 1:
	edge = ['1 2 0']
print('{} {}'.format(keta, len(edge)))
for e in edge:
	print(e)


import sys
sys.setrecursionlimit(2147483647)
INF = float('inf')
MOD = 10 ** 9 + 7
input = lambda : sys.stdin.readline().rstrip()

def iterate(L, n, m, edges, mode):
	if mode & 1 or L == 1:
		edges += [(1, n, L)]
		return (L + 1, n, m + 1, edges)
	else:
		edges = [(u, v, 2 * w) for (u, v, w) in edges]
		edges += [(n, n + 1, 0), (n, n + 1, 1)]
		return (2 * L, n + 1, m + 2, edges)

def resolve():
	L = int(input())
	res = [L % 2]
	while L != 1:
		if L & 1:
			L -= 1
		else:
			L //= 2
		res.append(L % 2)
	res.reverse()
	L = 1
	n = 2
	m = 1
	edges = [(1, 2, 0)]
	for mode in res[1:]:
		(L, n, m, edges) = iterate(L, n, m, edges, mode)
	print(n, m)
	for e in edges:
		print(*e)
resolve()


L = int(input())
n = 0
while 2 ** n <= L:
	n += 1
side_lst = []
rest = L - 2 ** (n - 1)
next_num = 2 ** (n - 1)
m = n
while rest > 0:
	if rest >= 2 ** (m - 2):
		side_lst.append([m - 1, n, next_num])
		next_num += 2 ** (m - 2)
		rest -= 2 ** (m - 2)
	m -= 1
print(n, len(side_lst) + (n - 1) * 2)
for i in side_lst:
	print(i[0], i[1], i[2])
for i in range(1, n):
	print(i, i + 1, 0)
	print(i, i + 1, 2 ** (i - 1))


L = int(input())
(A, N, D) = ([1 << i for i in range(21)], L.bit_length(), [])
for i in reversed(range(1, N)):
	D += [(i, i + 1, 0), (i, i + 1, A[N - 1 - i])]
P = A[N - 1]
for i in range(2, N + 1):
	s = N - i
	if L >> s & 1 == 1:
		D += [(1, i, P)]
		P += A[s]
print(N, len(D))
for (x, y, c) in D:
	print(x, y, c)


L = int(input())
k = L.bit_length()
ans = []
for i in range(1, k):
	ans.append([i, i + 1, 0])
	ans.append([i, i + 1, 1 << k - i - 1])
for i in range(k - 1):
	if L & 1 << i:
		mask = (1 << k + 1) - (1 << i + 1)
		w = L & mask
		ans.append([1, k - i, w])
print(k, len(ans))
for i in ans:
	print(*i)


L = int(input())
r = 0
while 2 ** r <= L:
	r += 1
r -= 1
ans = []
N = r + 1
for i in range(1, N):
	ans.append((i, i + 1, 0))
	ans.append((i, i + 1, 2 ** (i - 1)))
for t in range(N - 1, 0, -1):
	if L - 2 ** (t - 1) >= 2 ** r:
		ans.append((t, N, L - 2 ** (t - 1)))
		L -= 2 ** (t - 1)
print(N, len(ans))
for i in ans:
	print(i[0], i[1], i[2])


l = int(input())
v_count = 1
additional_e = []
while True:
	if l == 1:
		break
	elif l % 2 == 0:
		l = l // 2
		v_count += 1
	elif l % 2 == 1:
		l -= 1
		additional_e.append(v_count)
print(v_count, (v_count - 1) * 2 + len(additional_e))
for i in range(1, v_count):
	print(i, i + 1, 0)
	print(i, i + 1, 2 ** (i - 1))
num = 2 ** (v_count - 1)
for i in additional_e[::-1]:
	print(i, v_count, num)
	num = num + 2 ** (i - 1)


L = int(input())
(N, r) = (0, 1)
while r <= L:
	r *= 2
	N += 1
G = []
for i in range(1, N):
	G.append([i, i + 1, 0])
	G.append([i, i + 1, int(2 ** (i - 1))])
remain = L - int(2 ** (N - 1))
for i in range(N - 1, 0, -1):
	if remain == 0:
		break
	if remain >= int(2 ** (i - 1)):
		G.append([i, N, L - remain])
		remain -= int(2 ** (i - 1))
print(N, len(G))
for i in G:
	print(' '.join(map(str, i)))


L = int(input())
v = list(map(int, bin(L)[:2:-1]))
N = len(v) + 1
edges = []
unit = 1
for i in range(N - 1):
	L -= unit * v[i]
	edges.append((i + 1, i + 2, 0))
	edges.append((i + 1, i + 2, unit))
	if v[i]:
		edges.append((i + 1, N, L))
	unit *= 2
print(N, len(edges))
for (a, b, c) in edges:
	print(a, b, c)


import sys
from math import log2, floor
L = int(sys.stdin.readline().rstrip())

def main():
	n = floor(log2(L)) + 1
	m = 2 * (n - 1)
	edges = []
	for i in range(1, n):
		edges.append((i, i + 1, 0))
		edges.append((i, i + 1, 2 ** (i - 1)))
	cur = 2 ** (n - 1)
	q = L - cur
	for i in range(1, n):
		(q, r) = divmod(q, 2)
		if not r:
			continue
		else:
			edges.append((i, n, cur))
			cur += 2 ** (i - 1)
			m += 1
	yield (n, m)
	for e in edges:
		yield e

def __starting_point():
	ans = main()
	for i in ans:
		print(*i, sep=' ')
__starting_point()


import sys
readline = sys.stdin.buffer.readline
MOD = 10 ** 9 + 7
INF = float('INF')
sys.setrecursionlimit(10 ** 5)

def main():

	def calc(x):
		for i in range(100):
			if 2 ** (i + 1) > x:
				return i
	from collections import defaultdict
	l = int(input())
	n = calc(l) + 1
	edge = []
	for u in range(1, n):
		edge.append((u, u + 1, 0))
		edge.append((u, u + 1, 2 ** (u - 1)))
	mx = 2 ** (n - 1) - 1
	rem = l - 1 - mx
	bit = format(rem, 'b')
	bit = bit[::-1]
	cur = mx
	for (u, o) in enumerate(bit, 1):
		if o == '1':
			edge.append((u, n, cur + 1))
			cur += 2 ** (u - 1)
	print(n, len(edge))
	for (u, v, w) in edge:
		print(u, v, w)
main()


L = int(input())
N = L.bit_length()
edges = [[] for _ in range(N)]
for i in range(N - 1):
	edges[i].append((i + 1, 0))
	edges[i].append((i + 1, 2 ** i))
now = 2 ** (N - 1)
for i in range(N - 1)[::-1]:
	cnt = 2 ** i
	if L - now >= cnt:
		edges[i].append((N - 1, now))
		now += cnt
M = sum((len(edges[i]) for i in range(N)))
print(N, M)
for i in range(N):
	for (to, cost) in edges[i]:
		print(i + 1, to + 1, cost)


import math
L = int(input())
N = int(math.log(L, 2))
print(N + 1, bin(L)[3:].count('1') + 2 * N)
for i in range(1, N + 1):
	print(i, i + 1, 0)
	print(i, i + 1, 2 ** (i - 1))
tmp = 2 ** N
for i in range(N, 0, -1):
	if tmp + 2 ** (i - 1) - 1 <= L - 1:
		print(i, N + 1, tmp)
		tmp = tmp + 2 ** (i - 1)


L = int(input())
for l_max in range(1, 21):
	if 2 ** l_max > L:
		break
bits_sub = [None] * l_max
L_temp = L - 2 ** (l_max - 1)
for l in range(l_max):
	bits_sub[l] = L_temp % 2
	L_temp = L_temp // 2
N = l_max
M = 2 * (l_max - 1) + sum(bits_sub)
print(N, M)
for i in range(l_max - 1):
	for j in range(2):
		print(i + 1, i + 2, j * 2 ** i)
maxlen = 2 ** (l_max - 1)
for (i, bit) in enumerate(bits_sub):
	if bit == 0:
		continue
	for j in range(bit):
		print(i + 1, l_max, maxlen)
		maxlen += 2 ** i


import math
L = int(input())
s = int(math.log2(L))
N = s + 1
count = 0
graph = []
for i in range(N - 1, 0, -1):
	if L - 2 ** (i - 1) >= 2 ** s:
		graph.append([i, N, L - 2 ** (i - 1)])
		L = L - 2 ** (i - 1)
		count += 1
print(N, end=' ')
print(2 * (N - 1) + count)
for i in range(N, 1, -1):
	print(i - 1, end=' ')
	print(i, end=' ')
	print(0)
	print(i - 1, end=' ')
	print(i, end=' ')
	print(2 ** (i - 2))
for i in range(len(graph)):
	print(graph[i][0], end=' ')
	print(graph[i][1], end=' ')
	print(graph[i][2])


import sys

class paiza_fmt_input:

	def __init__(self):
		self.cur = 0
		self.all_input = []

	def input_all(self):
		for line in sys.stdin:
			self.all_input.append(line)

	def get_one_line_with_split(self):
		input_cur = self.all_input[self.cur]
		self.cur += 1
		splitted_input = input_cur.split()
		return splitted_input

def get_bit_list(num):
	bit_list = []
	for i in range(64):
		if num >> i & 1:
			bit_list.append(i)
	return bit_list

def solve(inputs):
	line1_input = list(map(int, inputs.get_one_line_with_split()))
	path_num = line1_input[0]
	bit_list = get_bit_list(path_num)
	max_bit = bit_list[-1]
	dags = []
	for i in range(max_bit):
		dags.append([i + 1, i + 2, 0])
		dags.append([i + 1, i + 2, pow(2, i)])
	end_node_no = bit_list[-1] + 1
	bit_list.pop()
	ofs_num_cur = pow(2, max_bit)
	while True:
		if not bit_list:
			break
		bit = bit_list.pop()
		dags.append([bit + 1, end_node_no, ofs_num_cur])
		ofs_num_cur += pow(2, bit)
	print(end_node_no, len(dags))
	for dag in dags:
		print(*dag)
inputs = paiza_fmt_input()
inputs.input_all()
solve(inputs)


import copy
n = int(input())
a = [2 ** x for x in range(0, 21)]
b = 0
for (i, name) in enumerate(a):
	b_copy = copy.deepcopy(b)
	b = name
	if b > n:
		break
ans = []
ans_l = []
c = n - b_copy
for j in range(i - 1)[::-1]:
	if a[j] <= c:
		c -= a[j]
		ans.append(j)
		ans_l.append(b_copy)
		b_copy += a[j]
N = i
H = 0
A = []
for k in range(1, i):
	A.append([k, k + 1, 0])
	A.append([k, k + 1, 2 ** (k - 1)])
	H += 2
	if k - 1 in ans:
		A.append([k, N, ans_l[ans.index(k - 1)]])
		H += 1
print(' '.join([str(N), str(H)]))
for kk in A:
	print(' '.join(list(map(str, kk))))


def solve(L):
	import math
	N = int(math.log2(L))
	grahp = []
	for i in range(1, N + 1):
		grahp.append([i, i + 1, 0])
		grahp.append([i, i + 1, 2 ** (i - 1)])
	for i in range(N, 0, -1):
		if L - 2 ** (i - 1) >= 2 ** N:
			L = L - 2 ** (i - 1)
			grahp.append([i, N + 1, L])
	M = len(grahp)
	print(N + 1, M)
	[print(' '.join([str(i) for i in g])) for g in grahp]

def __starting_point():
	L = int(input())
	solve(L)
__starting_point()


import math

def main():
	l = int(input())
	n = math.floor(math.log2(l)) + 1
	e = []
	for v in range(n - 1):
		v2 = 2 ** v
		e.append([v + 1, v + 2, 0])
		e.append([v + 1, v + 2, v2])
		if l >> v & 1:
			e.append([v + 1, n, l - v2])
			l -= v2
	print(n, len(e))
	for x in e:
		print(*x)
main()


L = int(input())
p = [1] * 21
N = 0
for i in range(20):
	p[i + 1] = p[i] * 2
	if p[i + 1] > L:
		N = i + 1
		break
ans = []
M = 0
for i in range(N - 1):
	ans.append([i + 1, i + 2, 0])
	ans.append([i + 1, i + 2, p[i]])
	M += 2
path = L - p[N - 1]
N2 = len(bin(path)) - 2
for i in range(N):
	if path & 1 == 1:
		ans.append([i + 1, N, L - p[i]])
		M += 1
		L -= p[i]
	path = path >> 1
print(' '.join(map(str, [N, M])))
for i in range(M):
	print(' '.join(map(str, ans[i])))


import math
L = int(input())
N = math.floor(math.log2(L)) + 1
M = N * 2 - 2
add_path = []
for i in range(1, N)[::-1]:
	if L - 2 ** (i - 1) >= 2 ** (N - 1):
		add_path.append([i, L - 2 ** (i - 1)])
		L -= 2 ** (i - 1)
print(N, M + len(add_path))
for i in range(1, N):
	print(i, i + 1, 0)
	print(i, i + 1, 2 ** (i - 1))
for i in add_path:
	print(i[0], N, i[1])


L = int(input())

def divideBin(n):
	d = 1
	ans = []
	while n > 0:
		(r, q) = divmod(n, 2)
		ans.append(q * d)
		d *= 2
		n = r
	return ans
divided = divideBin(L)
N = len(divided)
M = 2 * (N - 1) + len([x for x in divided if x != 0]) - 1
print(N, M)
for i in range(1, N):
	print(i, i + 1, 0)
	print(i, i + 1, pow(2, i - 1))
node = N - 1
value = divided[N - 1]
while node > 0:
	if divided[node - 1] != 0:
		print(node, N, value)
		value += divided[node - 1]
	node -= 1


l = int(input())
r = 0
g = []
while 2 ** r <= l:
	r += 1
for i in range(1, r):
	g.append((i, i + 1, 0))
	g.append((i, i + 1, 2 ** (i - 1)))
n = r
l -= 2 ** (r - 1)
edge = 2 ** (n - 1)
while l > 0:
	if l < 2 ** (r - 1):
		r -= 1
		continue
	l -= 2 ** (r - 1)
	g.append((r, n, edge))
	edge += 2 ** (r - 1)
print(n, len(g))
for (a, b, c) in g:
	print(a, b, c)


from collections import defaultdict, deque, Counter
from heapq import heappush, heappop, heapify
import math
import bisect
import random
from itertools import permutations, accumulate, combinations, product
import sys
import string
from bisect import bisect_left, bisect_right
from math import factorial, ceil, floor
from functools import reduce
INF = float('inf')

def LI():
	return list(map(int, sys.stdin.readline().split()))

def I():
	return int(sys.stdin.readline())

def LS():
	return sys.stdin.readline().split()

def S():
	return sys.stdin.readline().strip()

def IR(n):
	return [I() for i in range(n)]

def LIR(n):
	return [LI() for i in range(n)]

def SR(n):
	return [S() for i in range(n)]

def LSR(n):
	return [LS() for i in range(n)]

def SRL(n):
	return [list(S()) for i in range(n)]

def MSRL(n):
	return [[int(j) for j in list(S())] for i in range(n)]
mod = 1000000007
l = I()
ans = []
d = len(bin(l)) - 2
ret = 2 ** (d - 1)
remain = l - 2 ** (d - 1)
ret = 2 ** (d - 1)
for i in range(d - 1, 0, -1):
	ans += [(i, i + 1, 0)]
	ans += [(i, i + 1, 2 ** (i - 1))]
	if 1 << i - 1 & remain:
		ans += [(i, d, ret)]
		ret += 2 ** (i - 1)
print(d, len(ans))
for k in ans:
	print(*k)


def main():
	l = int(input())
	n = 1
	while 1 << n <= l:
		n += 1
	ans = []
	for i in range(n - 1):
		ans.append([i, i + 1, 0])
		ans.append([i, i + 1, 1 << i])
	l -= 1 << n - 1
	val = 1 << n - 1
	for p in range(n - 2, -1, -1):
		if l >= 1 << p:
			ans.append([p, n - 1, val])
			val += 1 << p
			l -= 1 << p
	print(n, len(ans))
	for (a, b, c) in ans:
		print(a + 1, b + 1, c)
main()


l = int(input())
n = l.bit_length()
edge = list()
for i in range(1, n):
	edge.append((i, i + 1, 0))
	edge.append((i, i + 1, 1 << i - 1))
t = l - (1 << n - 1)
cnt = (n - 1) * 2
while t:
	m = t.bit_length()
	edge.append((m, n, l - t))
	t -= 1 << m - 1
	cnt += 1
print(n, cnt)
for t in edge:
	print(*t)


L = int(input())
n = len(str(bin(L))) - 3
e = []
for i in range(n):
	e.append((i + 1, i + 2, 0))
	e.append((i + 1, i + 2, 2 ** (n - i - 1)))
h = 2 ** n
for (i, c) in enumerate(str(bin(L))[2:]):
	if c == '1' and i:
		e.append((1, i + 1, h))
		h += 2 ** (n - i)
print(n + 1, len(e))
for i in e:
	print(*i)


L = int(input())
N = L.bit_length()
C = []
for i in range(N - 1):
	C.append((N - i - 1, N - i, 1 << i))
	C.append((N - i - 1, N - i, 0))
v = 1
for i in range(N - 1):
	if v & L:
		L ^= v
		C.append((1, N - i, L))
	v <<= 1
print(N, len(C))
for (x, y, z) in C:
	print(x, y, z)


def f(k, L, p):
	m = L
	while m % 3 > 0:
		p += [[k + 1, 20, (m - 1) * 3 ** k]]
		m = m - 1
	if m == 0:
		print(20, len(p))
		for l in p:
			print(' '.join([str(t) for t in l]))
		return
	for i in range(3):
		p += [[k + 1, k + 2, i * 3 ** k]]
	m = m // 3
	if m > 0:
		return f(k + 1, m, p)
f(0, int(input()), [])


import math
l = int(input())
node = int(math.log2(l)) + 1
edges = []
for _from in range(1, node):
	edges.append([_from, _from + 1, 0])
	edges.append([_from, _from + 1, 2 ** (_from - 1)])
count = 2 ** (node - 1)
lack = l - count
length = 2 ** (node - 1)
for _from in range(node - 1, 0, -1):
	if not lack:
		break
	add_line = 2 ** (_from - 1)
	if add_line > lack:
		continue
	edges.append([_from, node, length])
	lack -= add_line
	length += add_line
print((node, len(edges)))
for (_from, to, length) in edges:
	print((_from, to, length))


L = int(input())
rec = []
r = 0
K = L
while K > 1:
	K //= 2
	r += 1
N = r + 1
for i in range(1, N):
	rec.append([i, i + 1, 0])
	rec.append([i, i + 1, 2 ** (i - 1)])
for i in range(N - 1, 0, -1):
	if L - 2 ** (i - 1) >= 2 ** r:
		rec.append([i, N, L - 2 ** (i - 1)])
		L -= 2 ** (i - 1)
rec.sort()
print(N, len(rec))
for (i, j, k) in rec:
	print(i, j, k)


L = int(input())
ans = []
m = 0
add = -1
mask = 16777215
for i in range(24):
	mask >>= 1
	d = 24 - i - 1
	if ~mask & L != 0:
		if add == -1:
			n = d + 1
			add = 1 << d
			b = 1
			for i in range(1, d + 1):
				ans.append(str(i) + ' ' + str(i + 1) + ' 0')
				ans.append(str(i) + ' ' + str(i + 1) + ' ' + str(b))
				b *= 2
				m += 2
		else:
			ans.append(str(d + 1) + ' ' + str(n) + ' ' + str(add))
			add += 1 << d
			m += 1
		L &= mask
print(n, m)
for i in ans:
	print(i)


L = int(input())
count = 0
k = 1
max = 0
LL = format(L, 'b')
N = len(LL)
M = (len(LL) - 1) * 2 + LL.count('1') - 1
print(N, M)
max = 2 ** (N - 1) - 1
for n in range(1, N):
	print(n, n + 1, 0)
	print(n, n + 1, k)
	k *= 2
	if LL[::-1][n - 1] == '1' and n != N:
		print(n, N, max + 1)
		max += 2 ** (n - 1)


def get_node(num):
	now_num = 1
	count = 1
	while 1:
		if now_num > num:
			count -= 1
			break
		count += 1
		now_num *= 2
	return count

def get_ans_data(node_num):
	ans_data = []
	for i in range(1, node_num):
		data = [i, i + 1, 2 ** (i - 1)]
		data2 = [i, i + 1, 0]
		ans_data.append(data)
		ans_data.append(data2)
	return ans_data

def main():
	num = int(input())
	node_num = get_node(num)
	ans_data = get_ans_data(node_num)
	now_path = 2 ** (node_num - 1)
	now_num = node_num - 1
	for i in range(now_num, 0, -1):
		now_data = 2 ** (i - 1)
		if num - now_data >= now_path:
			ans_data.append((i, node_num, num - now_data))
			num -= now_data
	print((node_num, len(ans_data)))
	for data in ans_data:
		print(' '.join(list(map(str, data))))

def __starting_point():
	main()
__starting_point()


import sys

def solve(L: int):
	sL = '{:b}'.format(L)
	N = len(sL)
	M = 2 * (N - 1) + sL.count('1') - 1
	print((N, M))
	for i in range(N - 1):
		print((i + 1, i + 2, 0))
		print((i + 1, i + 2, 2 ** i))
	for (i, c) in enumerate(reversed(sL[1:])):
		if c == '0':
			continue
		print((i + 1, N, int(sL[:-i - 1], 2) * 2 ** (i + 1)))

def main():

	def iterate_tokens():
		for line in sys.stdin:
			for word in line.split():
				yield word
	tokens = iterate_tokens()
	L = int(next(tokens))
	solve(L)

def __starting_point():
	main()
__starting_point()


L = int(input())
for i in range(20):
	if 2 ** i > L:
		N = i
		break
else:
	N = 20
M = N * 2 - 2
add_path = []
for i in range(1, N)[::-1]:
	if L - 2 ** (i - 1) >= 2 ** (N - 1):
		add_path.append([i, L - 2 ** (i - 1)])
		L -= 2 ** (i - 1)
print(N, M + len(add_path))
for i in range(1, N):
	print(i, i + 1, 0)
	print(i, i + 1, 2 ** (i - 1))
for i in add_path:
	print(i[0], N, i[1])


import math
L = int(input())
r = math.floor(math.log2(L))
N = r + 1
E_list = []
for i in range(1, N):
	E_list.append((i, i + 1, 0))
	E_list.append((i, i + 1, 2 ** (r - i)))
	if L - 2 ** (N - i - 1) >= 2 ** r:
		E_list.append((1, i + 1, L - 2 ** (N - i - 1)))
		L -= 2 ** (N - i - 1)
M = len(E_list)
print(N, M)
for e in E_list:
	print(e[0], e[1], e[2])


import sys, collections as cl, bisect as bs
sys.setrecursionlimit(100000)
input = sys.stdin.readline
mod = 10 ** 9 + 7
Max = sys.maxsize

def l():
	return list(map(int, input().split()))

def m():
	return map(int, input().split())

def onem():
	return int(input())

def s(x):
	a = []
	if len(x) == 0:
		return []
	aa = x[0]
	su = 1
	for i in range(len(x) - 1):
		if aa != x[i + 1]:
			a.append([aa, su])
			aa = x[i + 1]
			su = 1
		else:
			su += 1
	a.append([aa, su])
	return a

def jo(x):
	return ' '.join(map(str, x))

def max2(x):
	return max(map(max, x))

def In(x, a):
	k = bs.bisect_left(a, x)
	if k != len(a) and a[k] == x:
		return True
	else:
		return False

def pow_k(x, n):
	ans = 1
	while n:
		if n % 2:
			ans *= x
		x *= x
		n >>= 1
	return ans
n = onem()
nn = n
N = 1
co = 0
while True:
	N *= 2
	if n < N:
		break
	co += 1
	if co > 19:
		break
data = []
ap = 1
for i in range(1, co + 1):
	data.append([i, i + 1, 0])
	data.append([i, i + 1, ap])
	ap *= 2
for i in range(co, -1, -1):
	if n - pow(2, i) >= pow(2, co):
		data.append([i + 1, co + 1, n - pow(2, i)])
		n -= pow(2, i)
print(co + 1, len(data))
for i in range(len(data)):
	print(jo(data[i]))


import sys

def I():
	return int(sys.stdin.readline().rstrip())
L = I()
N = L.bit_length()
M = 2 * (N - 1)
ANS = [[i, i + 1, 0] for i in range(1, N)] + [[i, i + 1, 2 ** (N - 1 - i)] for i in range(1, N)]
a = 1 << N - 1
for i in range(N - 2, -1, -1):
	if L >> i & 1:
		ANS.append([1, N - i, a])
		M += 1
		a += 1 << i
print(N, M)
for i in range(M):
	print(*ANS[i])


import sys
L = int(input()) - 1
if L == 1:
	print(2, 2)
	print(1, 2, 0)
	print(1, 2, 1)
	sys.exit()
M = 0
threelist = []
j = 1
i = 1
while i <= 10 ** 6:
	i = 3 ** j - 1
	threelist.append(i)
	j += 1
threelist = threelist[::-1]
j = 0
while True:
	if L >= threelist[j]:
		break
	else:
		j += 1
node = len(threelist) - j
PATH = []
for i in range(2, 2 + node):
	PATH.append((i, i + 1, 0))
	PATH.append((i, i + 1, 3 ** (node + 2 - i - 1)))
	PATH.append((i, i + 1, 2 * 3 ** (node + 2 - i - 1)))
	M += 3
while L > 0:
	j = 0
	while True:
		if L >= threelist[j]:
			break
		else:
			j += 1
	k = len(threelist) - j
	rest = L - (3 ** k - 1)
	PATH.append((1, node + 2 - k, rest))
	M += 1
	L = rest - 1
	if L == 0:
		PATH.append((1, node + 2, 0))
		M += 1
		break
	if L == 1:
		PATH.append((1, node + 2, 0))
		PATH.append((1, node + 2, 1))
		M += 2
		break
print(node + 2, M)
for pa in PATH:
	print(pa[0], pa[1], pa[2])


L = int(input())
L2 = bin(L)[2:]
N = len(L2)
L2d = L2[1:]
L2u = int('0b' + L2, 0) - int('0b' + L2d, 0)
L2u2 = L2u // 2
tmp = 1
M = 0
Ans = []
if L2u != 0:
	tmpN = N
	while tmp != L2u:
		Ans.append([tmpN - 1, tmpN, 0])
		Ans.append([tmpN - 1, tmpN, tmp])
		tmp *= 2
		tmpN -= 1
		M += 2
flag = 0
for i in range(len(L2d)):
	if L2d[i] == '1' and flag == 0:
		Ans.append([1, i + 2, L2u])
		tmp = 2 ** (N - i - 2)
		M += 1
		flag = 1
		B = L2u
	elif L2d[i] == '1':
		Ans.append([1, i + 2, B + tmp])
		B = B + tmp
		tmp = 2 ** (N - i - 2)
		M += 1
print(*[N, M])
for i in range(M):
	print(*Ans[i])


import sys
sys.setrecursionlimit(10 ** 9)
INF = 10 ** 18
MOD = 10 ** 9 + 7

def input():
	return sys.stdin.readline().rstrip()

def main():
	L = int(input())
	tmp = L
	tmp2 = L
	l = []
	while tmp2 != 0:
		c = 0
		while tmp != 1:
			tmp //= 2
			c += 1
		l.append(c)
		tmp2 -= 2 ** c
		tmp = tmp2
	N = l[0] + 1
	M = 0
	ans = []
	w = 1
	for i in range(l[0]):
		ans.append((i + 1, i + 2, 0))
		ans.append((i + 1, i + 2, w))
		M += 2
		w *= 2
	for x in l[1:]:
		ans.append((x + 1, N, w))
		w += 2 ** x
		M += 1
	print(N, M)
	for z in ans:
		print(*z)
main()


L = int(input())
N = 1
l = L
while l // 2 >= 1:
	N += 1
	l //= 2
G = [[] for _ in range(N + 1)]
for i in range(1, N):
	G[i].append([i + 1, 0])
	G[i].append([i + 1, 2 ** (N - 1 - i)])
M = 2 * (N - 1)
tmp = 2 ** (N - 1)
for i in range(N - 2, -1, -1):
	if L >> i & 1:
		G[1].append([N - i, tmp])
		tmp += 2 ** i
		M += 1
if N > 20 or M > 60:
	print('error')
print(N, M)
for i in range(1, N):
	for j in G[i]:
		print(i, *j)


import math
L = int(input())
r = int(math.log2(L))
res = []
for i in range(1, r + 1):
	res.append([i, i + 1, 0])
	res.append([i, i + 1, 2 ** (i - 1)])
for t in range(r, 0, -1):
	if L >= 2 ** r + 2 ** (t - 1):
		L -= 2 ** (t - 1)
		res.append([t, r + 1, L])
print(r + 1, len(res))
for i in range(len(res)):
	print(res[i][0], res[i][1], res[i][2])


import math
l = int(input())
r = math.floor(math.log2(l))
n = r + 1
pow2r = pow(2, r)
lst = list(([i, i + 1, 0] for i in range(1, n))) + list(([i, i + 1, pow(2, i - 1)] for i in range(1, n)))
for i in range(1, n)[::-1]:
	p = pow(2, i - 1)
	if l - p >= pow2r:
		lst.append([i, n, l - p])
		l -= p
print(n, len(lst))
for (u, v, w) in lst:
	print(u, v, w)


L = int(input())
r = 0
while 2 ** (r + 1) <= L:
	r += 1
E = []
for i in range(1, r + 1):
	E.append((i, i + 1, 0))
	E.append((i, i + 1, 2 ** (i - 1)))
N = r + 1
for i in range(N - 1, 0, -1):
	if L - 2 ** (i - 1) >= 2 ** r:
		E.append((i, N, L - 2 ** (i - 1)))
		L -= 2 ** (i - 1)
print(N, len(E))
for e in E:
	print(e[0], e[1], e[2])


import math
l = int(input())
n = math.floor(math.log2(l)) + 1
edge = []
for i in range(1, n):
	edge.append((i, i + 1, 0))
for (j, i) in enumerate(reversed(range(1, n))):
	edge.append((i, i + 1, 2 ** j))
l2 = l - 2 ** (n - 1)
c = 2 ** (n - 1)
while l2 > 0:
	l_mini = 1
	while l_mini * 2 <= l2:
		l_mini *= 2
	edge.append((1, n - int(math.log2(l_mini)), c))
	l2 -= l_mini
	c += l_mini
print(n, len(edge))
for i in range(len(edge)):
	print(*edge[i])


L = int(input())
L_list = list(str(bin(L)))
del L_list[0:2]
N = len(L_list)
for i in range(N):
	L_list[i] = int(L_list[i])
M = 2 * N - 2
for n in range(1, N):
	if L_list[n] == 1:
		M += 1
print(N, M)
for i in range(N):
	L_list[i] = int(L_list[i])
for n in range(N - 1):
	print(n + 1, n + 2, 0)
	print(n + 1, n + 2, 2 ** (N - n - 2))
A = 2 ** (N - 1)
for n in range(1, N):
	if L_list[n] == 1:
		print(1, n + 1, A)
		A += 2 ** (N - n - 1)


L = int(input())
digit = L.bit_length()
if 2 ** digit > L:
	digit -= 1
ans = []
for i in range(1, digit + 1):
	ans.append([i, i + 1, 0])
	ans.append([i, i + 1, 2 ** (i - 1)])
L = L - 2 ** digit
tmp = 0
for i in range(digit, 0, -1):
	if L - 2 ** (i - 1) >= 0:
		ans.append([i, digit + 1, 2 ** digit + tmp])
		L -= 2 ** (i - 1)
		tmp += 2 ** (i - 1)
print(digit + 1, len(ans))
for a in ans:
	print(*a)


import sys
sys.setrecursionlimit(10 ** 6)
input = sys.stdin.readline
from math import floor, sqrt, factorial, hypot, log
from heapq import heappop, heappush, heappushpop
from collections import Counter, defaultdict, deque
from itertools import accumulate, permutations, combinations, product, combinations_with_replacement
from bisect import bisect_left, bisect_right
from copy import deepcopy
from fractions import gcd
from random import randint

def ceil(a, b):
	return (a + b - 1) // b
inf = float('inf')
mod = 10 ** 9 + 7

def pprint(*A):
	for a in A:
		print(*a, sep='\n')

def INT_(n):
	return int(n) - 1

def MI():
	return map(int, input().split())

def MF():
	return map(float, input().split())

def MI_():
	return map(INT_, input().split())

def LI():
	return list(MI())

def LI_():
	return [int(x) - 1 for x in input().split()]

def LF():
	return list(MF())

def LIN(n: int):
	return [I() for _ in range(n)]

def LLIN(n: int):
	return [LI() for _ in range(n)]

def LLIN_(n: int):
	return [LI_() for _ in range(n)]

def LLI():
	return [list(map(int, l.split())) for l in input()]

def I():
	return int(input())

def F():
	return float(input())

def ST():
	return input().replace('\n', '')

def main():
	L = I()
	power = 1
	N = 1
	while power << 1 <= L:
		power <<= 1
		N += 1
	ans = []
	for i in range(N - 1):
		ans.append((i + 1, i + 2, 0))
		ans.append((i + 1, i + 2, 1 << i))
	for i in range(N - 1)[::-1]:
		X = L - (1 << i)
		if X >= power:
			ans.append((i + 1, N, X))
			L -= 1 << i
	M = len(ans)
	print(N, M)
	for a in ans:
		print(*a)

def __starting_point():
	main()
__starting_point()


L = t = int(input())
X = []
B = 4
while L:
	X.append(L % B)
	L //= B
E = []
N = len(X) * 2
for (i, x) in enumerate(X[:-1]):
	r = B ** i
	t -= r * x
	for k in range(0, x):
		E.append((2 * i + 1, 2 * i + 2, r * k))
	E.append((2 * i + 2, 2 * i + 3, 0))
	for k in range(x, B):
		E.append((2 * i + 1, 2 * i + 3, r * k))
	E.append((2 * i + 2, N, t))
for k in range(0, X[-1]):
	E.append((N - 1, N, B ** (len(X) - 1) * k))
print(N, len(E))
for e in E:
	print(*e)


n = int(input())
cnt = 0
while 2 ** cnt - 1 < n:
	cnt += 1
cnt -= 1
graph = []
for i in range(cnt):
	graph.append((1 + i, 2 + i, 2 ** i))
	graph.append((1 + i, 2 + i, 0))
existmax = 2 ** cnt - 1
for i in range(1, cnt + 1)[::-1]:
	if 2 ** (i - 1) - 1 + existmax + 1 <= n - 1:
		graph.append((i, cnt + 1, existmax + 1))
		existmax = existmax + 1 + 2 ** (i - 1) - 1
L = len(graph)
print(cnt + 1, L)
for i in graph:
	print(*i)


L = int(input())
N = L.bit_length()
node = [i for i in range(1, N + 1)]
edge = []
for (x, y) in zip(node[:-1], node[1:]):
	edge.append((x, y, 0))
x = 1
while L > 1:
	if L & 1:
		L -= 1
		edge.append((x, N, L))
	else:
		L //= 2
		edge.append((x, x + 1, L))
		x += 1
print(N, len(edge))
for e in edge:
	print(*e)


L = int(input()) - 1
for i in range(1, 21):
	if 2 ** i > L + 1:
		N = i
		break
M = 2 * (N - 1)
l = []
for i in range(1, N):
	l.append((i, i + 1, 2 ** (i - 1)))
	l.append((i, i + 1, 0))
L -= 2 ** (N - 1) - 1
t = 2 ** (N - 1)
for i in range(N - 1, -1, -1):
	if 2 ** i <= L:
		l.append((i + 1, N, t))
		L -= 2 ** i
		t += 2 ** i
		M += 1
print(N, M)
for i in l:
	print(*i)


import math
L = int(input())
r = math.floor(math.log2(L))
N = r + 1
graph = []
for i in range(1, r + 1):
	graph.append([i, i + 1, 0])
	graph.append([i, i + 1, 2 ** (i - 1)])
for t in range(N - 1, 0, -1):
	if L - 2 ** (t - 1) >= 2 ** r:
		graph.append([t, N, L - 2 ** (t - 1)])
		L -= 2 ** (t - 1)
print(N, len(graph))
for g in graph:
	print(*g)


l = int(input())
n = l.bit_length()
ANS = []
for i in range(1, n):
	ANS.append((i, i + 1, 0))
	ANS.append((i, i + 1, 2 ** (i - 1)))
for i in reversed(range(1, n)):
	if l - 2 ** (i - 1) >= 2 ** (n - 1):
		l -= 2 ** (i - 1)
		ANS.append((i, n, l))
print(n, len(ANS))
for ans in ANS:
	print(*ans)


l = int(input())
for i in range(1, 21):
	if 2 ** i > l:
		r = i - 1
		break
ans = []
for i in range(r):
	ans.append((i + 1, i + 2, 0))
	ans.append((i + 1, i + 2, 2 ** i))
now = 2 ** r - 1
for i in range(r, 0, -1):
	if 2 ** (i - 1) + now <= l - 1:
		ans.append((i, r + 1, now + 1))
		now += 2 ** (i - 1)
print(r + 1, len(ans))
for x in ans:
	print(*x)


L = int(input())

def power2(i):
	power = 0
	while i > 1:
		i //= 2
		power += 1
	return power
r = power2(L)
N = r + 1
M = []
for i in range(1, N):
	M.append([i, i + 1, 0])
	M.append([i, i + 1, 2 ** (i - 1)])
for i in range(N - 1, 0, -1):
	if L - 2 ** (i - 1) >= 2 ** r:
		M.append([i, N, L - 2 ** (i - 1)])
		L -= 2 ** (i - 1)
M.sort()
print(N, len(M))
for i in M:
	print(i[0], i[1], i[2])


l = int(input())
if l <= 60:
	n = 2
	print(n, l)
	for i in range(l):
		print(1, n, i)
	exit()
p = []
temp = l
while temp > 0:
	p.append(temp % 2)
	temp //= 2
ans = []
res = []
n = len(p)
temp = 1
for i in range(n - 1):
	ans.append([i + 1, i + 2, 0])
	ans.append([i + 1, i + 2, temp])
	temp *= 2
m = l - temp + 1
s = n
fuga = temp
while m > 0 and s > 0:
	if m > temp:
		m -= temp
		ans.append([s, n, fuga])
		fuga += temp
	temp //= 2
	s -= 1
print(n, len(ans))
t = 1
for x in ans:
	print(x[0], x[1], x[2])


L = int(input()) - 1
N = []
n = 0
for i in range(20):
	if 2 ** i - 1 > L:
		break
	n = i
c = 2 ** n - 1
d = 2 ** (n - 1)
m = 2 * n
n += 1
for i in range(n - 1, 0, -1):
	A = [(i, i + 1, 0), (i, i + 1, d)]
	if L - (d - 1) > c:
		L -= d
		m += 1
		A.append((i, n, L + 1))
	N.append(A)
	d //= 2
print(n, m)
for a in N:
	for b in a:
		print(*b)


def in_list(l, l_t, a):
	l[a] = l_t
ans_list = [[] for _ in range(60)]
p = 0
l = int(input())
bin_str = format(l, '020b')
for i in range(20):
	c = 0
	if c == 0 and str(bin_str)[i] == '1':
		c = 1
		n = 20 - i
		k = i
		break
for j in range(1, n):
	in_list(ans_list, [j, j + 1, 0], p)
	p += 1
	in_list(ans_list, [j, j + 1, 2 ** (n - 1 - j)], p)
	p += 1
c = 2 ** (n - 1)
for m in range(k + 1, 20):
	if str(bin_str[m]) == '1':
		in_list(ans_list, [1, n + m - 20 + 1, c], p)
		p += 1
		c += 2 ** (19 - m)
print(n, p)
for q in range(p):
	print(ans_list[q][0], ans_list[q][1], ans_list[q][2])


def graph(L):
	beki = 1
	for n in range(20):
		beki *= 2
		if beki > L:
			break
	ans = []
	Li = 1
	for i in range(n):
		ans += [(i + 1, i + 2, 0)]
		ans += [(i + 1, i + 2, Li)]
		Li *= 2
	Lnext = Li
	nokori_kosu = L - Li
	i = n - 1
	way_i = Li // 2
	while nokori_kosu > 0:
		while way_i > nokori_kosu:
			way_i //= 2
			i -= 1
		ans += [(i + 1, n + 1, Lnext)]
		Lnext += way_i
		nokori_kosu -= way_i
	print(n + 1, len(ans))
	for x in ans:
		print(*x)
L = int(input())
graph(L)


L = int(input())
k = 1
power = 4
while L >= power:
	k += 1
	power *= 2
power = 1
ans = []
for i in range(k):
	ans.append([k - i, k + 1 - i, 0])
	ans.append([k - i, k + 1 - i, power])
	power *= 2
N = k + 1
l = power
rest = L - l
while rest > 0:
	power = 1
	k = 0
	while rest >= power * 2:
		power *= 2
		k += 1
	ans.append([1, N - k, l])
	l += power
	rest -= power
print(*[N, len(ans)])
for i in ans:
	print(*i)


L = int(input())
b = []
while L > 0:
	b.append(L % 2)
	L = int(L / 2)
p = []
cost = 1
for i in range(len(b), 1, -1):
	p.append((i - 1, i, 0))
	p.append((i - 1, i, cost))
	cost *= 2
cost2 = cost
for i in range(2, len(b) + 1):
	cost2 = int(cost2 / 2)
	if b[-i] % 2 == 1:
		p.append((1, i, cost))
		cost += cost2
print(len(b), len(p))
for tp in p:
	print(tp[0], tp[1], tp[2])


import math
L = int(input())
n = int(math.log2(L))
w1 = pow(2, n - 1)
w1n = bin(L - pow(2, n))
p = 2 * n + w1n.count('1')
print(str(n + 1) + ' ' + str(p))
print('1 2 0')
print('1 2 ' + str(w1))
for i in range(2, n + 1):
	print(str(i) + ' ' + str(i + 1) + ' 0')
	print(str(i) + ' ' + str(i + 1) + ' ' + str(pow(2, n - i)))
w = L - 1
for i in range(len(w1n) - 2):
	if w1n[-1] == '1':
		print('1 ' + str(n + 1 - i) + ' ' + str(w))
		w -= pow(2, i)
	w -= pow(2, i)
	w1n = w1n[:-1]
	if w1n.count('1') == 0:
		break


length = int(input())
goal = 0
while 2 ** goal <= length:
	goal += 1
edge = []
for i in range(1, goal):
	edge.append((i, i + 1, 0))
	edge.append((i, i + 1, 2 ** (i - 1)))
remain = length - 2 ** (goal - 1)

def addedge(r, s):
	if r == 1:
		edge.append((1, goal, s))
		return
	if r == 2:
		edge.append((1, goal, s))
		edge.append((1, goal, s + 1))
		return
	else:
		k = 0
		while 2 ** k <= r:
			k += 1
		remain = r - 2 ** (k - 1)
		edge.append((k, goal, s))
		if remain:
			addedge(remain, s + 2 ** (k - 1))
if remain:
	shift = 2 ** (goal - 1)
	addedge(remain, shift)
print(goal, len(edge))
for (v1, v2, w) in edge:
	print(v1, v2, w)


l = int(input())
n = 0
while 2 ** n <= l:
	n += 1
p = []
for i in range(1, n):
	p.append((i, i + 1, 0))
	p.append((i, i + 1, 2 ** (i - 1)))
	if l // 2 ** (i - 1) % 2 == 1:
		p.append((i, n, l // 2 ** i * 2 ** i))
m = len(p)
print(n, m)
for i in p:
	print(*i)


def all_your_paths_are_different_lengths(L: int) -> tuple:
	if L == 1:
		return (2, [(1, 2, 0)])
	r = 0
	while 2 ** (r + 1) <= L:
		r = r + 1
	N = r + 1
	edges = []
	power2 = 1
	for i in range(1, N):
		edges.append((i, i + 1, 0))
		edges.append((i, i + 1, power2))
		power2 = power2 * 2
	for t in range(N - 1, 0, -1):
		if L - 2 ** (t - 1) >= 2 ** r:
			edges.append((t, N, L - 2 ** (t - 1)))
			L = L - 2 ** (t - 1)
	return (N, edges)
L = int(input())
(N, edges) = all_your_paths_are_different_lengths(L)
print(N, len(edges))
for (u, v, w) in edges:
	print(u, v, w)


from collections import defaultdict, deque
import sys, heapq, bisect, math, itertools, string, queue, datetime
sys.setrecursionlimit(10 ** 8)
INF = float('inf')
mod = 10 ** 9 + 7
eps = 10 ** (-7)

def inp():
	return int(input())

def inpl():
	return list(map(int, input().split()))

def inpls():
	return list(input().split())
L = int(input())
N = L.bit_length()
Lines = []
for i in range(1, N):
	Lines.append([i, i + 1, 0])
	Lines.append([i, i + 1, 1 << N - i - 1])
tmp = 1 << N - 1
for k in reversed(range(N - 1)):
	if L >> k & 1:
		Lines.append([1, N - k, tmp])
		tmp += 1 << k
print(N, len(Lines))
for (a, zu, nyan) in Lines:
	print(a, zu, nyan)


L = int(input())
N = len(bin(L)[2:])
M = 0
Lines = []
for i in range(N - 1):
	M += 2
	Lines.append((i + 1, i + 2, 0))
	Lines.append((i + 1, i + 2, 2 ** i))
tmp = 2 ** (N - 1)
for (i, j) in enumerate(bin(L)[3:], 1):
	if j == '1':
		M += 1
		Lines.append((N - i, N, tmp))
		tmp += 2 ** (N - i - 1)
print(N, M)
for Line in Lines:
	print('{} {} {}'.format(Line[0], Line[1], Line[2]))


L = int(input())
(N, D, p) = (L.bit_length(), [], print)
P = 1 << N - 1
for i in range(2, N + 1):
	s = N - i
	D += [(i - 1, i, 0), (i - 1, i, 1 << s)]
	if L >> s & 1:
		D += [(1, i, P)]
		P += 1 << s
p(N, len(D))
for (x, y, c) in D:
	p(x, y, c)


def iin():
	return int(input())
l = iin()
stack = []
ans = [[1, 2, 0]]
x = l
while True:
	if x == 1:
		break
	while x % 2 == 0 and x > 2:
		x //= 2
		stack.append('*2')
	if x == 1:
		break
	x -= 1
	stack.append('+1')
last_v_num = 2
x = 1
while len(stack) > 0:
	op = stack.pop()
	if op == '+1':
		x += 1
		ans.append([1, last_v_num, x - 1])
	elif op == '*2':
		x *= 2
		for i in range(len(ans)):
			ans[i][2] *= 2
		ans.append([last_v_num, last_v_num + 1, 0])
		ans.append([last_v_num, last_v_num + 1, 1])
		last_v_num += 1
N = last_v_num
M = len(ans)
print(N, M)
for (u, v, w) in ans:
	print(u, v, w)


L = int(input())
r = 0
while pow(2, r + 1) <= L:
	r += 1
N = r + 1
edge = []
for i in range(N - 1):
	edge.append((i + 1, i + 2, 0))
	edge.append((i + 1, i + 2, pow(2, i)))
M = r * 2
remain = L - pow(2, r)
for i in range(N - 1)[::-1]:
	if remain < pow(2, i):
		continue
	else:
		edge.append((i + 1, N, L - remain))
		M += 1
		remain -= pow(2, i)
print(N, M)
for e in edge:
	print(' '.join(map(str, e)))


l = int(input())
k = l
cnt = 0
while k > 1:
	k //= 2
	cnt += 1
edge = [[] for _ in range(cnt)]
e = 2 * cnt
for i in range(cnt):
	edge[i].append((i + 1, 0))
	edge[i].append((i + 1, 2 ** i))
for i in reversed(range(cnt)):
	if l - 2 ** i >= 2 ** cnt:
		edge[i].append((cnt, l - 2 ** i))
		l -= 2 ** i
		e += 1
print(cnt + 1, e)
for i in range(cnt):
	for (j, d) in edge[i]:
		print(i + 1, j + 1, d)


import sys
input = sys.stdin.readline
import math
import bisect
import heapq
from collections import defaultdict
from collections import deque
from collections import Counter
from functools import lru_cache
MOD = 10 ** 9 + 7
INF = float('inf')
AZ = 'abcdefghijklmnopqrstuvwxyz'

def I():
	return int(input().strip())

def S():
	return input().strip()

def IL():
	return list(map(int, input().split()))

def SL():
	return list(map(str, input().split()))

def ILs(n):
	return list((int(input()) for _ in range(n)))

def SLs(n):
	return list((input().strip() for _ in range(n)))

def ILL(n):
	return [list(map(int, input().split())) for _ in range(n)]

def SLL(n):
	return [list(map(str, input().split())) for _ in range(n)]

def DD(arg):
	return defaultdict(arg)

def inv(n):
	return pow(n, MOD - 2, MOD)
kaijo_memo = []

def kaijo(n):
	if len(kaijo_memo) > n:
		return kaijo_memo[n]
	if len(kaijo_memo) == 0:
		kaijo_memo.append(1)
	while len(kaijo_memo) <= n:
		kaijo_memo.append(kaijo_memo[-1] * len(kaijo_memo) % MOD)
	return kaijo_memo[n]
gyaku_kaijo_memo = []

def gyaku_kaijo(n):
	if len(gyaku_kaijo_memo) > n:
		return gyaku_kaijo_memo[n]
	if len(gyaku_kaijo_memo) == 0:
		gyaku_kaijo_memo.append(1)
	while len(gyaku_kaijo_memo) <= n:
		gyaku_kaijo_memo.append(gyaku_kaijo_memo[-1] * pow(len(gyaku_kaijo_memo), MOD - 2, MOD) % MOD)
	return gyaku_kaijo_memo[n]

def nCr(n, r):
	if n == r:
		return 1
	if n < r or r < 0:
		return 0
	ret = 1
	ret = ret * kaijo(n) % MOD
	ret = ret * gyaku_kaijo(r) % MOD
	ret = ret * gyaku_kaijo(n - r) % MOD
	return ret

def factorization(n):
	arr = []
	temp = n
	for i in range(2, int(-(-n ** 0.5 // 1)) + 1):
		if temp % i == 0:
			cnt = 0
			while temp % i == 0:
				cnt += 1
				temp //= i
			arr.append([i, cnt])
	if temp != 1:
		arr.append([temp, 1])
	if arr == []:
		arr.append([n, 1])
	return arr

def make_divisors(n):
	divisors = []
	for i in range(1, int(n ** 0.5) + 1):
		if n % i == 0:
			divisors.append(i)
			if i != n // i:
				divisors.append(n // i)
	return divisors

def make_primes(N):
	max = int(math.sqrt(N))
	seachList = [i for i in range(2, N + 1)]
	primeNum = []
	while seachList[0] <= max:
		primeNum.append(seachList[0])
		tmp = seachList[0]
		seachList = [i for i in seachList if i % tmp != 0]
	primeNum.extend(seachList)
	return primeNum

def gcd(a, b):
	while b:
		(a, b) = (b, a % b)
	return a

def lcm(a, b):
	return a * b // gcd(a, b)

def count_bit(n):
	count = 0
	while n:
		n &= n - 1
		count += 1
	return count

def base_10_to_n(X, n):
	if X // n:
		return base_10_to_n(X // n, n) + [X % n]
	return [X % n]

def base_n_to_10(X, n):
	return sum((int(str(X)[-i - 1]) * n ** i for i in range(len(str(X)))))

def base_10_to_n_without_0(X, n):
	X -= 1
	if X // n:
		return base_10_to_n_without_0(X // n, n) + [X % n]
	return [X % n]

def int_log(n, a):
	count = 0
	while n >= a:
		n //= a
		count += 1
	return count
L = I()
N = len(bin(L)) - 2
ans = []
for i in range(1, N):
	if L % 2:
		ans.append([i, N, L - 1])
	ans.append([i, i + 1, L // 2])
	ans.append([i, i + 1, 0])
	L //= 2
print(N, len(ans))
for (a, b, c) in ans:
	print(a, b, c)


L = int(input())
r = 0
while 2 ** (r + 1) <= L:
	r += 1
N = r + 1
edges = []
for i in range(1, N):
	edges.append([i, i + 1, 0])
	edges.append([i, i + 1, 2 ** (i - 1)])
for t in reversed(range(1, N)):
	if L - 2 ** (t - 1) >= 2 ** r:
		edges.append([t, N, L - 2 ** (t - 1)])
		L -= 2 ** (t - 1)
print(N, len(edges))
for v in edges:
	print(*v)


def getN():
	return int(input())

def getNM():
	return map(int, input().split())

def getList():
	return list(map(int, input().split()))

def getArray(intn):
	return [int(input()) for i in range(intn)]

def input():
	return sys.stdin.readline().rstrip()

def rand_N(ran1, ran2):
	return random.randint(ran1, ran2)

def rand_List(ran1, ran2, rantime):
	return [random.randint(ran1, ran2) for i in range(rantime)]

def rand_ints_nodup(ran1, ran2, rantime):
	ns = []
	while len(ns) < rantime:
		n = random.randint(ran1, ran2)
		if not n in ns:
			ns.append(n)
	return sorted(ns)

def rand_query(ran1, ran2, rantime):
	r_query = []
	while len(r_query) < rantime:
		n_q = rand_ints_nodup(ran1, ran2, 2)
		if not n_q in r_query:
			r_query.append(n_q)
	return sorted(r_query)
from collections import defaultdict, deque, Counter
from sys import exit
from decimal import *
import heapq
from math import sqrt, pi
from fractions import gcd
import random
import string
import copy
from itertools import combinations, permutations, product
from operator import mul, itemgetter
from functools import reduce
from bisect import bisect_left, bisect_right
import sys
sys.setrecursionlimit(1000000000)
mod = 10 ** 9 + 7
L = int(input())
Lstr = bin(L)[2:]
N = len(Lstr)
M = (N - 1) * 2 + (Lstr.count('1') - 1)
print(N, M)
c = 1
for i in range(1, N):
	print(i, i + 1, c)
	print(i, i + 1, 0)
	c *= 2
c = 2 ** (N - 1)
for (i, v) in enumerate(Lstr[::-1]):
	if i == N - 1:
		continue
	if v == '1':
		print(i + 1, N, c)
		c += 2 ** i


def solve(l):
	n = 0
	while 2 ** n <= l:
		n += 1
	E = []
	for i in range(n - 1, -1, -1):
		x = 2 ** i
		if i != n - 1:
			E.append((i, i + 1, 0))
			E.append((i, i + 1, x))
		if l - x >= 2 ** (n - 1):
			E.append((i, n - 1, l - x))
			l -= x
	print(n, len(E))
	for (u, v, x) in E:
		print(u + 1, v + 1, x)
l = int(input())
solve(l)