import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.TreeSet;

public class cheese_gen {

	final static int MAX = 30;
	final static int ONE_HUNDRED_THOUSAND = 100000;
	final static Random rand = new Random(32965046509650868L);
	final static int TEN_MILLION = 10000000;

	public static void main(String[] args) throws IOException {
		for (int test = 1; test <= 50; test++) {
			System.out.println("Generating test #"
					+ ((test < 10 ? "0" : "") + test));
			PrintWriter out = new PrintWriter((test < 10 ? "0" : "") + test);
			long[] p, r, d, s;
			switch (test) {
			case 1:
				p = new long[] { 13, 10 };
				r = new long[] { 0, 1 };
				d = new long[] { 4, 3 };
				s = new long[] { 4, 2 };
				break;
			case 2:
				p = new long[] { 1 };
				r = new long[] { 0 };
				d = new long[] { 2 };
				s = new long[] { 1 };
				break;
			case 3:
				p = new long[] { 10, 10 };
				r = new long[] { 0, 0 };
				d = new long[] { 5, 4 };
				s = new long[] { 6, 4 };
				break;
			case 4:
				p = new long[MAX];
				r = new long[MAX];
				d = new long[MAX];
				s = new long[MAX];
				for (int i = 0; i < MAX; i++) {
					p[i] = ONE_HUNDRED_THOUSAND;
					r[i] = TEN_MILLION - 1;
					d[i] = TEN_MILLION;
				}
				for (int i = 0; i < MAX; i++) {
					s[i] = ONE_HUNDRED_THOUSAND;
				}
				break;
			case 5:
				p = new long[MAX];
				r = new long[MAX];
				d = new long[MAX];
				s = new long[MAX];
				for (int i = 0; i < MAX; i++) {
					p[i] = ONE_HUNDRED_THOUSAND;
					r[i] = TEN_MILLION - 1;
					d[i] = TEN_MILLION;
				}
				for (int i = 0; i < MAX; i++) {
					s[i] = 1;
				}
				break;
			case 6:
				p = new long[MAX];
				r = new long[MAX];
				d = new long[MAX];
				s = new long[MAX];
				for (int i = 0; i < MAX; i++) {
					p[i] = ONE_HUNDRED_THOUSAND;
					r[i] = 0;
					d[i] = TEN_MILLION;
				}
				for (int i = 0; i < MAX; i++) {
					s[i] = ONE_HUNDRED_THOUSAND;
				}
				break;
			case 7:
				p = new long[MAX];
				r = new long[MAX];
				d = new long[MAX];
				s = new long[] { 1 };
				for (int i = 0; i < MAX; i++) {
					p[i] = ONE_HUNDRED_THOUSAND;
					r[i] = TEN_MILLION - 1;
					d[i] = TEN_MILLION;
				}
				break;
			case 8:
				p = new long[] { ONE_HUNDRED_THOUSAND };
				r = new long[] { 0 };
				d = new long[] { TEN_MILLION };
				s = new long[] { ONE_HUNDRED_THOUSAND };
				break;
			case 9:
				p = new long[] { ONE_HUNDRED_THOUSAND };
				r = new long[] { 0 };
				d = new long[] { TEN_MILLION };
				s = new long[MAX];
				for (int i = 0; i < MAX; i++) {
					s[i] = ONE_HUNDRED_THOUSAND;
				}
				break;
			case 10:
				p = new long[] { 1 };
				r = new long[] { 0 };
				d = new long[] { TEN_MILLION };
				s = new long[MAX];
				for (int i = 0; i < MAX; i++) {
					s[i] = ONE_HUNDRED_THOUSAND;
				}
				break;
			case 11:
			case 12:
			case 13: {
				TreeSet<Integer> ts = new TreeSet<Integer>();
				int n = MAX;
				while (ts.size() < 2 * n) {
					ts.add(rand.nextInt(TEN_MILLION + 1));
				}
				int[] a = new int[ts.size()];
				{
					int k = 0;
					for (int i : ts) {
						a[k++] = i;
					}
				}
				p = new long[n];
				r = new long[n];
				d = new long[n];
				s = new long[] { 1 };
				for (int i = 0; i < n; i++) {
					r[i] = a[2 * i];
					p[i] = Math.min(ONE_HUNDRED_THOUSAND, a[2 * i + 1] - r[i]);
					d[i] = r[i] + 1 + rand.nextInt(TEN_MILLION - (int) r[i]);
				}
			}
				break;
			case 14:
				p = new long[] { 4, 2 };
				r = new long[] { 0, 0 };
				d = new long[] { 2, 1 };
				s = new long[] { 1, 2 };
				break;
			case 15:
				p = new long[] { 93, 4, 72 };
				r = new long[] { 876, 906, 877 };
				d = new long[] { 932, 987, 941 };
				s = new long[] { 61 };
				break;
			case 16:
				p = new long[] { 51, 7 };
				r = new long[] { 927, 927 };
				d = new long[] { 976, 949 };
				s = new long[] { 77 };
				break;
			case 17:
				p = new long[] { 47, 79, 48 };
				r = new long[] { 135, 899, 899 };
				d = new long[] { 757, 967, 944 };
				s = new long[] { 96, 52 };
				break;
			case 18:
				p = new long[] { 57, 81, 94, 50, 92 };
				r = new long[] { 289, 9998, 450, 9998, 7108 };
				d = new long[] { 6621, 10000, 4307, 9999, 9792 };
				s = new long[] { 47, 7, 39 };
				break;
			case 19:
				p = new long[] { 84, 47, 48, 8 };
				r = new long[] { 223, 8625, 5764, 8625 };
				d = new long[] { 2765, 9277, 7886, 9242 };
				s = new long[] { 70, 72, 92 };
				break;
			case 20:
				p = new long[] { 65, 47, 91, 70, 42 };
				r = new long[] { 3104, 8916, 9779, 9319, 9843 };
				d = new long[] { 7483, 9300, 9955, 9887, 9989 };
				s = new long[] { 1 };
				break;
			case 21:
				p = new long[] { 4, 3 };
				r = new long[] { 0, 0 };
				d = new long[] { 2, 1 };
				s = new long[] { 4, 3 };
				break;
			case 22:
				p = new long[] { 10, 10 };
				r = new long[] { 0, 0 };
				d = new long[] { 5, 5 };
				s = new long[] { 6, 4 };
				break;
			default:
				int n = 1 + rand.nextInt(MAX);
				int m = 1 + rand.nextInt(MAX);
				if (test % 13 == 0) {
					n = MAX;
					m = MAX;
				}
				p = new long[n];
				for (int i = 0; i < p.length; i++) {
					p[i] = 1 + rand.nextInt(ONE_HUNDRED_THOUSAND);
				}
				r = new long[n];
				for (int i = 0; i < r.length; i++) {
					r[i] = rand.nextInt(TEN_MILLION);
				}
				d = new long[n];
				for (int i = 0; i < d.length; i++) {
					d[i] = r[i] + 1 + rand.nextInt(TEN_MILLION - (int) r[i]);
				}
				s = new long[m];
				for (int i = 0; i < s.length; i++) {
					s[i] = 1 + rand.nextInt(ONE_HUNDRED_THOUSAND / 1000);
				}
				break;
			}
			write(p, r, d, s, out);
			out.close();
		}
	}

	private static void write(long[] p, long[] r, long[] d, long[] s,
			PrintWriter out) {
		long ans = new cheese_aa().solve(p, r, d, s);
		if (ans < 0) {
			ans = -ans / cheese_aa.PREC;
			ans += rand.nextInt(TEN_MILLION);
			for (int i = 0; i < d.length; i++) {
				d[i] = Math.max(r[i] + 1, d[i] - ans);
			}
		}
		out.println(p.length + " " + s.length);
		for (int i = 0; i < p.length; i++) {
			out.println(p[i] + " " + r[i] + " " + d[i]);
		}
		for (int i = 0; i < s.length; i++) {
			out.println(s[i]);
		}
	}

	public static class cheese_aa {

		static final long PREC = 100000;

		class Vertex {
			public Vertex(int i) {
				n = i;
				edges = new ArrayList<Edge>();
			}

			ArrayList<Edge> edges;
			int n;
			boolean used;
		}

		class Edge {
			public Edge(Vertex v1, Vertex v2, long c2) {
				x = v1;
				y = v2;
				c = c2;
				f = 0;
				r = null;
			}

			Vertex x, y;
			Edge r;
			long f, c;
		}

		class Graph {
			public Graph(int n) {
				v = new Vertex[n];
				for (int i = 0; i < v.length; i++) {
					v[i] = new Vertex(i);
				}
			}

			Vertex[] v;

			public void addEdge(int x, int y, long c) {
				Edge e = new Edge(v[x], v[y], c);
				Edge er = new Edge(v[y], v[x], 0);
				e.r = er;
				er.r = e;
				v[x].edges.add(e);
				v[y].edges.add(er);
			}

			public long maxFlow(int s, int t) {
				long flow = 0;
				for (long scale = 1L << 60; scale > 0; scale >>= 2) {
					for (int i = 0; i < v.length; i++) {
						v[i].used = false;
					}
					min = Long.MAX_VALUE;
					while (dfs(v[s], v[t], scale, min)) {
						for (int i = 0; i < v.length; i++) {
							v[i].used = false;
						}
						flow += min;
					}
				}
				return flow;
			}

			private long min;

			private boolean dfs(Vertex x, Vertex t, long scale, long f) {
				if (x == t) {
					min = f;
					return true;
				}
				x.used = true;
				for (Edge e : x.edges) {
					if (e.c - e.f >= scale && !e.y.used
							&& dfs(e.y, t, scale, Math.min(f, e.c - e.f))) {
						e.f += min;
						e.r.f -= min;
						return true;
					}
				}
				return false;
			}
		}

		private long solve(long[] p2, long[] r2, long[] d2, long[] s2) {
			long[] p = p2.clone();
			long[] r = r2.clone();
			long[] d = d2.clone();
			long[] s = s2.clone();
			long sp = 0;
			int n = p.length;
			int m = s.length;
			for (int i = 0; i < p.length; i++) {
				p[i] *= PREC;
				r[i] *= PREC;
				d[i] *= PREC;
				sp += p[i];
			}
			long left = -1L * TEN_MILLION * ONE_HUNDRED_THOUSAND;
			long right = 1L * TEN_MILLION * ONE_HUNDRED_THOUSAND;
			for (int i = 0; i < s.length; i++) {
				s[i] = -s[i];
			}
			Arrays.sort(s);
			long sum = 0;
			for (int i = 0; i < s.length; i++) {
				s[i] = -s[i];
				sum += s[i];
			}
			while (right - left > 1) {
				long middle = (left + right) / 2;
				TreeSet<Long> ts = new TreeSet<Long>();
				for (int i = 0; i < p.length; i++) {
					ts.add(r[i]);
					ts.add(d[i] + middle);
				}
				long[] t = new long[ts.size()];
				{
					int k = 0;
					for (long x : ts) {
						t[k++] = x;
					}
				}
				Graph g = new Graph(1 + n + m * (t.length - 1) + t.length - 1
						+ 1);
				for (int i = 0; i < p.length; i++) {
					g.addEdge(0, i + 1, p[i]);
					for (int k = 0; k + 1 < t.length; k++) {
						if (r[i] <= t[k] && t[k + 1] <= d[i] + middle) {
							int sh = n + 1 + k * m;
							for (int j = 0; j < s.length; j++) {
								long c = (s[j] - (j + 1 < s.length ? s[j + 1]
										: 0))
										* (t[k + 1] - t[k]);
								g.addEdge(i + 1, sh + j, c);
							}
						}
					}
				}
				for (int k = 0; k + 1 < t.length; k++) {
					int sh = n + 1 + k * m;
					for (int j = 0; j < s.length; j++) {
						long c = (j + 1)
								* (s[j] - (j + 1 < s.length ? s[j + 1] : 0))
								* (t[k + 1] - t[k]);
						g.addEdge(sh + j, 1 + n + m * (t.length - 1) + k, c);
					}
					g.addEdge(1 + n + m * (t.length - 1) + k, 1 + n + m
							* (t.length - 1) + t.length - 1, sum
							* (t[k + 1] - t[k]));
				}
				long flow = g.maxFlow(0, 1 + n + m * (t.length - 1) + t.length
						- 1);
				if (flow == sp) {
					right = middle;
				} else {
					left = middle;
				}
			}
			return right;
		}
	}

}
