import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.StringTokenizer;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskG solver = new TaskG();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskG {
    static class Intersector {
        long minxplusy = Long.MIN_VALUE;
        long maxxplusy = Long.MAX_VALUE;
        long minxminusy = Long.MIN_VALUE;
        long maxxminusy = Long.MAX_VALUE;

        void update(long kx, long ky, long a) {
            if (Math.abs(kx) != Math.abs(ky)) throw new RuntimeException();
            if (kx == 0) {
                if (a <= 0) return;
                minxplusy = Long.MAX_VALUE;
                maxxplusy = Long.MIN_VALUE;
                minxminusy = Long.MAX_VALUE;
                maxxminusy = Long.MIN_VALUE;
                return;
            }
            if (kx > 0) {
                if (ky > 0) {
                    maxxplusy = Math.min(maxxplusy, safeDivide(-a, kx));
                } else {
                    maxxminusy = Math.min(maxxminusy, safeDivide(-a, kx));
                }
            } else {
                if (ky < 0) {
                    minxplusy = Math.max(minxplusy, safeDivide(a + (-kx) - 1, -kx));
                } else {
                    minxminusy = Math.max(minxminusy, safeDivide(a + (-kx) - 1, -kx));
                }
            }
        }

        private long safeDivide(long a, long b) {
            if (a > 0) return a / b; else return (a - b + 1) / b;
        }
    }

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        int l = in.nextInt();
        boolean[] know = new boolean[l + 1];
        long[] k = new long[l + 1];
        long[] ax = new long[l + 1];
        long[] ay = new long[l + 1];
        know[0] = true;
        know[l] = true;
        k[l] = 1;
        boolean knowP = false;
        long px = 0;
        long py = 0;
        for (int i = 0; i < n; ++i) {
            long t = in.nextLong();
            long x = in.nextLong();
            long y = in.nextLong();
            if ((x + y + t) % 2 != 0) {
                out.println("NO");
                return;
            }
            int when = (int) (t % l);
            long ck = -t / l;
            if (!know[when]) {
                know[when] = true;
                k[when] = ck;
                ax[when] = x;
                ay[when] = y;
            } else {
                if (knowP) {
                    if (k[when] * px + ax[when] != ck * px + x || Math.abs(k[when] * (double) px + ax[when] - ck * (double) px - x) > 1e62) {
                        out.println("NO");
                        return;
                    }
                    if (k[when] * py + ay[when] != ck * py + y || Math.abs(k[when] * (double) py + ay[when] - ck * (double) py - y) > 1e62) {
                        out.println("NO");
                        return;
                    }
                } else {
                    knowP = true;
                    long numx = x - ax[when];
                    long numy = y - ay[when];
                    long den = k[when] - ck;
                    if (numx % den != 0 || numy % den != 0) {
                        out.println("NO");
                        return;
                    }
                    px = numx / den;
                    py = numy / den;
                }
            }
        }

        {
            Intersector intersector = new Intersector();
            int prev = 0;
            for (int i = 1; i <= l; ++i) if (know[i]) {
                long dk = k[i] - k[prev];
                long dax = ax[i] - ax[prev];
                long day = ay[i] - ay[prev];
                for (int kx = -1; kx <= 1; kx += 2) {
                    for (int ky = -1; ky <= 1; ky += 2) {
                       intersector.update(kx * dk, ky * dk, kx * dax + ky * day - (i - prev));
                    }
                }
                prev = i;
            }
            if (knowP) {
                if (px + py < intersector.minxplusy || px + py > intersector.maxxplusy) {
                    out.println("NO");
                    return;
                }
                if (px - py < intersector.minxminusy || px - py > intersector.maxxminusy) {
                    out.println("NO");
                    return;
                }
                if ((px + py + l) % 2 != 0) {
                    out.println("NO");
                    return;
                }
            } else {
                if (intersector.minxplusy > intersector.maxxplusy) {
                    out.println("NO");
                    return;
                }
                if (intersector.minxminusy > intersector.maxxminusy) {
                    out.println("NO");
                    return;
                }
                long xplusy;
                if (intersector.minxplusy == Long.MIN_VALUE) {
                    if (intersector.maxxplusy == Long.MAX_VALUE) {
                        xplusy = 0;
                    } else {
                        xplusy = intersector.maxxplusy - 1;
                    }
                } else {
                    xplusy = intersector.minxplusy;
                }
                long xminusy;
                if (intersector.minxminusy == Long.MIN_VALUE) {
                    if (intersector.maxxminusy == Long.MAX_VALUE) {
                        xminusy = 0;
                    } else {
                        xminusy = intersector.maxxminusy - 1;
                    }
                } else {
                    xminusy = intersector.minxminusy;
                }
                if ((xplusy + l) % 2 != 0) {
                    if (xplusy < intersector.maxxplusy) {
                        ++xplusy;
                    } else {
                        out.println("NO");
                        return;
                    }
                }
                if ((xminusy + l) % 2 != 0) {
                    if (xminusy < intersector.maxxminusy) {
                        ++xminusy;
                    } else {
                        out.println("NO");
                        return;
                    }
                }
                px = (xplusy + xminusy) / 2;
                py = (xplusy - xminusy) / 2;
            }
        }

        int prev = 0;
        for (int i = 1; i <= l; ++i) if (know[i]) {
            long dk = k[i] - k[prev];
            long dax = ax[i] - ax[prev];
            long day = ay[i] - ay[prev];
            long dx = dk * px + dax;
            long dy = dk * py + day;
            if ((Math.abs(dx) + Math.abs(dy) > i - prev) || (Math.abs(dx) + Math.abs(dy) + (i - prev)) % 2 != 0) throw new RuntimeException();
            int extra = (int) ((i - prev - Math.abs(dx) - Math.abs(dy)) / 2);
            while (dx > 0) {
                out.print('R');
                --dx;
            }
            while (dx < 0) {
                out.print('L');
                ++dx;
            }
            while (dy > 0) {
                out.print('U');
                --dy;
            }
            while (dy < 0) {
                out.print('D');
                ++dy;
            }
            for (int j = 0; j < extra; ++j) {
                out.print("LR");
            }
            prev = i;
        }
        out.println();
    }
}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream), 32768);
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    public long nextLong() {
        return Long.parseLong(next());
    }

}

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.StringTokenizer;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        ChallengeG solver = new ChallengeG();
        solver.solve(1, in, out);
        out.close();
    }
}

class ChallengeG {
    static class Intersector {
        long minxplusy = Long.MIN_VALUE;
        long maxxplusy = Long.MAX_VALUE;
        long minxminusy = Long.MIN_VALUE;
        long maxxminusy = Long.MAX_VALUE;

        void update(long kx, long ky, long a) {
            if (Math.abs(kx) != Math.abs(ky)) throw new RuntimeException();
            if (kx == 0) {
                if (a <= 0) return;
                minxplusy = Long.MAX_VALUE;
                maxxplusy = Long.MIN_VALUE;
                minxminusy = Long.MAX_VALUE;
                maxxminusy = Long.MIN_VALUE;
                return;
            }
            if (kx > 0) {
                if (ky > 0) {
                    maxxplusy = Math.min(maxxplusy, safeDivide(-a, kx));
                } else {
                    maxxminusy = Math.min(maxxminusy, safeDivide(-a, kx));
                }
            } else {
                if (ky < 0) {
                    minxplusy = Math.max(minxplusy, safeDivide(a + (-kx) - 1, -kx));
                } else {
                    minxminusy = Math.max(minxminusy, safeDivide(a + (-kx) - 1, -kx));
                }
            }
        }

        private long safeDivide(long a, long b) {
            if (a > 0) return a / b; else return (a - b + 1) / b;
        }
    }

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        int l = in.nextInt();
        boolean[] know = new boolean[l + 1];
        long[] k = new long[l + 1];
        long[] ax = new long[l + 1];
        long[] ay = new long[l + 1];
        know[0] = true;
        know[l] = true;
        k[l] = 1;
        boolean knowP = false;
        long px = 0;
        long py = 0;
        for (int i = 0; i < n; ++i) {
            long t = in.nextLong();
            long x = in.nextLong();
            long y = in.nextLong();
            if ((x + y + t) % 2 != 0) {
                out.println("NO");
                return;
            }
            int when = (int) (t % l);
            long ck = -t / l;
            if (!know[when]) {
                know[when] = true;
                k[when] = ck;
                ax[when] = x;
                ay[when] = y;
            } else {
                if (knowP) {
                    if (k[when] * px + ax[when] != ck * px + x || Math.abs(k[when] * (double) px + ax[when] - ck * (double) px - x) > 1e62) {
                        out.println("NO");
                        return;
                    }
                    if (k[when] * py + ay[when] != ck * py + y || Math.abs(k[when] * (double) py + ay[when] - ck * (double) py - y) > 1e62) {
                        out.println("NO");
                        return;
                    }
                } else {
                    knowP = true;
                    long numx = x - ax[when];
                    long numy = y - ay[when];
                    long den = k[when] - ck;
                    if (numx % den != 0 || numy % den != 0) {
                        out.println("NO");
                        return;
                    }
                    px = numx / den;
                    py = numy / den;
                }
            }
        }

        {
            Intersector intersector = new Intersector();
            int prev = 0;
            for (int i = 1; i <= l; ++i) if (know[i]) {
                long dk = k[i] - k[prev];
                long dax = ax[i] - ax[prev];
                long day = ay[i] - ay[prev];
                for (int kx = -1; kx <= 1; kx += 2) {
                    for (int ky = -1; ky <= 1; ky += 2) {
                       intersector.update(kx * dk, ky * dk, kx * dax + ky * day - (i - prev));
                    }
                }
                prev = i;
            }
            if (knowP) {
                if (px + py < intersector.minxplusy || px + py > intersector.maxxplusy) {
                    out.println("NO");
                    return;
                }
                if (px - py < intersector.minxminusy || px - py > intersector.maxxminusy) {
                    out.println("NO");
                    return;
                }
                if ((px + py + l) % 2 != 0) {
                    out.println("NO");
                    return;
                }
            } else {
                if (intersector.minxplusy > intersector.maxxplusy) {
                    out.println("NO");
                    return;
                }
                if (intersector.minxminusy > intersector.maxxminusy) {
                    out.println("NO");
                    return;
                }
                long xplusy;
                if (intersector.minxplusy == Long.MIN_VALUE) {
                    if (intersector.maxxplusy == Long.MAX_VALUE) {
                        xplusy = 0;
                    } else {
                        xplusy = intersector.maxxplusy - 1;
                    }
                } else {
                    xplusy = intersector.minxplusy;
                }
                long xminusy;
                if (intersector.minxminusy == Long.MIN_VALUE) {
                    if (intersector.maxxminusy == Long.MAX_VALUE) {
                        xminusy = 0;
                    } else {
                        xminusy = intersector.maxxminusy - 1;
                    }
                } else {
                    xminusy = intersector.minxminusy;
                }
                if ((xplusy + l) % 2 != 0) {
                    if (xplusy < intersector.maxxplusy) {
                        ++xplusy;
                    } else {
                        out.println("NO");
                        return;
                    }
                }
                if ((xminusy + l) % 2 != 0) {
                    if (xminusy < intersector.maxxminusy) {
                        ++xminusy;
                    } else {
                        out.println("NO");
                        return;
                    }
                }
                px = (xplusy + xminusy) / 2;
                py = (xplusy - xminusy) / 2;
            }
        }

        int prev = 0;
        for (int i = 1; i <= l; ++i) if (know[i]) {
            long dk = k[i] - k[prev];
            long dax = ax[i] - ax[prev];
            long day = ay[i] - ay[prev];
            long dx = dk * px + dax;
            long dy = dk * py + day;
            if ((Math.abs(dx) + Math.abs(dy) > i - prev) || (Math.abs(dx) + Math.abs(dy) + (i - prev)) % 2 != 0) throw new RuntimeException();
            int extra = (int) ((i - prev - Math.abs(dx) - Math.abs(dy)) / 2);
            while (dx > 0) {
                out.print('R');
                --dx;
            }
            while (dx < 0) {
                out.print('L');
                ++dx;
            }
            while (dy > 0) {
                out.print('U');
                --dy;
            }
            while (dy < 0) {
                out.print('D');
                ++dy;
            }
            for (int j = 0; j < extra; ++j) {
                out.print("LR");
            }
            prev = i;
        }
        out.println();
    }
}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream), 32768);
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    public long nextLong() {
        return Long.parseLong(next());
    }

}

import static java.lang.Double.parseDouble;
import static java.lang.Integer.parseInt;
import static java.lang.Long.parseLong;
import static java.lang.Math.abs;
import static java.lang.Math.floorDiv;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.System.exit;
import static java.util.Arrays.fill;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class G {

	static BufferedReader in;
	static PrintWriter out;
	static StringTokenizer tok;

//	static final Random rng = new Random(42);
//	static boolean rngOk;

	static void solve() throws Exception {
		int n = nextInt();
		int l = nextInt();
//		int n = rng.nextInt(40) + 1;
//		int l = rng.nextInt(15) + 1;
//		long rngX[] = new long[l + 1];
//		long rngY[] = new long[l + 1];
//		for (int i = 0; i < l; i++) {
//			long dx, dy;
//			switch (rng.nextInt(4)) {
//			case 0:
//				dx = 1;
//				dy = 0;
//				break;
//			case 1:
//				dx = -1;
//				dy = 0;
//				break;
//			case 2:
//				dx = 0;
//				dy = 1;
//				break;
//			case 3:
//				dx = 0;
//				dy = -1;
//				break;
//			default:
//				throw new AssertionError();
//			}
//			rngX[i + 1] = rngX[i] + dx;
//			rngY[i + 1] = rngY[i] + dy;
//		}
		long t[] = new long[n];
		long x[] = new long[n];
		long y[] = new long[n];
		{
			long pt = 0;
			long px = 0;
			long py = 0;
			for (int i = 0; i < n; i++) {
				long ct = nextLong();
				long cx = nextLong();
				long cy = nextLong();
//				long ct = pt + rng.nextInt(40) + 1;
//				long cx = (ct / l) * rngX[l] + rngX[(int) (ct % l)];
//				long cy = (ct / l) * rngY[l] + rngY[(int) (ct % l)];
//				if (rng.nextInt(10) == 0) {
//					cx += rng.nextInt(5) - 2;
//				}
//				if (rng.nextInt(10) == 0) {
//					cy += rng.nextInt(5) - 2;
//				}
				if (ct - pt < abs(cx - px) + abs(cy - py) || ((ct ^ cx ^ cy) & 1) != 0) {
					out.print("NO");
					return;
				}
				t[i] = ct;
				x[i] = cx + cy;
				y[i] = cx - cy;
				pt = ct;
				px = cx;
				py = cy;
			}
		}
		long lt[] = new long[l + 1];
		long lx[] = new long[l + 1];
		long ly[] = new long[l + 1];
		fill(lt, -1);
		lt[0] = 0;
		lx[0] = 0;
		ly[0] = 0;
		long shiftXmin = -l;
		long shiftXmax = l;
		long shiftYmin = -l;
		long shiftYmax = l;
		for (int i = 0; i < n; i++) {
			int j = (int) (t[i] % l);
			if (lt[j] >= 0) {
				long its = (t[i] - lt[j]) / l;
				if ((x[i] - lx[j]) % its != 0 || ((y[i] - ly[j]) % its != 0)) {
					out.print("NO");
					return;
				}
				shiftXmin = max(shiftXmin, (x[i] - lx[j]) / its);
				shiftXmax = min(shiftXmax, (x[i] - lx[j]) / its);
				shiftYmin = max(shiftYmin, (y[i] - ly[j]) / its);
				shiftYmax = min(shiftYmax, (y[i] - ly[j]) / its);
			} else {
				lt[j] = t[i];
				lx[j] = x[i];
				ly[j] = y[i];
			}
		}
		lt[l] = 0;
		lx[l] = 0;
		ly[l] = 0;
//		System.err.println(Arrays.toString(lt));
//		System.err.println(Arrays.toString(lx));
//		System.err.println(Arrays.toString(ly));
		{
			int pi = 0;
			for (int i = 1; i <= l; i++) {
				if (lt[i] < 0) {
					continue;
				}
				long its = (lt[i] - lt[pi] - (i - pi)) / l;
				if (its == 0) {
					if (i - pi < abs(lx[i] - lx[pi]) || i - pi < abs(ly[i] - ly[pi])) {
						out.print("NO");
						return;
					}
				} else {
					long dx = lx[i] - lx[pi];
					long dy = ly[i] - ly[pi];
					// dx - (i - pi) <= shiftX * its
					// dx + (i - pi) >= shiftX * its
					if (its > 0) {
						shiftXmin = max(shiftXmin, floorDiv(dx - (i - pi) + its - 1,  its));
						shiftXmax = min(shiftXmax, floorDiv(dx + (i - pi), its));
						shiftYmin = max(shiftYmin, floorDiv(dy - (i - pi) + its - 1, its));
						shiftYmax = min(shiftYmax, floorDiv(dy + (i - pi), its));
					} else {
						shiftXmin = max(shiftXmin, floorDiv(dx + (i - pi) + its + 1, its));
						shiftXmax = min(shiftXmax, floorDiv(dx - (i - pi), its));
						shiftYmin = max(shiftYmin, floorDiv(dy + (i - pi) + its + 1, its));
						shiftYmax = min(shiftYmax, floorDiv(dy - (i - pi), its));
					}
				}
				pi = i;
			}
			if (((shiftXmin ^ l) & 1) != 0) {
				++shiftXmin;
			}
			if (((shiftXmax ^ l) & 1) != 0) {
				--shiftXmax;
			}
			if (((shiftYmin ^ l) & 1) != 0) {
				++shiftYmin;
			}
			if (((shiftYmax ^ l) & 1) != 0) {
				--shiftYmax;
			}
			if (shiftXmin > shiftXmax || shiftYmin > shiftYmax) {
				out.print("NO");
				return;
			}
		}
		{
			long shiftX = shiftXmin;
			long shiftY = shiftYmin;
			long cx = 0;
			long cy = 0;
			int pi = 0;
			for (int i = 1; i <= l; i++) {
				if (lt[i] < 0) {
					continue;
				}
				long its = (lt[i] - i) / l;
				long nx = lx[i] - shiftX * its;
				long ny = ly[i] - shiftY * its;
				while (pi < i) {
					boolean xUp = nx > cx;
					boolean yUp = ny > cy;
					out.print(xUp ? (yUp ? 'R' : 'U') : (yUp ? 'D' : 'L'));
					if (xUp) {
						++cx;
					} else {
						--cx;
					}
					if (yUp) {
						++cy;
					} else {
						--cy;
					}
					++pi;
				}
				if (cx != nx || cy != ny) {
//					System.err.println(n + " " + l);
//					System.err.println(Arrays.toString(rngX));
//					System.err.println(Arrays.toString(rngY));
//					System.err.println(Arrays.toString(t));
//					System.err.println(Arrays.toString(x));
//					System.err.println(Arrays.toString(y));
//					System.err.println(Arrays.toString(lt));
//					System.err.println(Arrays.toString(lx));
//					System.err.println(Arrays.toString(ly));
//					System.err.println(shiftX + " " + shiftY);
//					System.err.println(i + " " + cx + " " + cy + " " + nx + " " + ny);
					throw new AssertionError();
				}
			}
		}
//		rngOk = true;
	}

	static int nextInt() throws IOException {
		return parseInt(next());
	}

	static long nextLong() throws IOException {
		return parseLong(next());
	}

	static double nextDouble() throws IOException {
		return parseDouble(next());
	}

	static String next() throws IOException {
		while (tok == null || !tok.hasMoreTokens()) {
			tok = new StringTokenizer(in.readLine());
		}
		return tok.nextToken();
	}

	public static void main(String[] args) {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(new OutputStreamWriter(System.out));
//			if (true) while (true) {
//				rngOk = false;
//				solve();
////				if (!rngOk) {
////					throw new AssertionError();
////				}
//				System.err.println("PASS");
//			}
			solve();
			in.close();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			exit(1);
		}
	}
}

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.StringTokenizer;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskG solver = new TaskG();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskG {
    static class Intersector {
        long minxplusy = Long.MIN_VALUE;
        long maxxplusy = Long.MAX_VALUE;
        long minxminusy = Long.MIN_VALUE;
        long maxxminusy = Long.MAX_VALUE;

        void update(long kx, long ky, long a) {
            if (Math.abs(kx) != Math.abs(ky)) throw new RuntimeException();
            if (kx == 0) {
                if (a <= 0) return;
                minxplusy = Long.MAX_VALUE;
                maxxplusy = Long.MIN_VALUE;
                minxminusy = Long.MAX_VALUE;
                maxxminusy = Long.MIN_VALUE;
                return;
            }
            if (kx > 0) {
                if (ky > 0) {
                    maxxplusy = Math.min(maxxplusy, safeDivide(-a, kx));
                } else {
                    maxxminusy = Math.min(maxxminusy, safeDivide(-a, kx));
                }
            } else {
                if (ky < 0) {
                    minxplusy = Math.max(minxplusy, safeDivide(a + (-kx) - 1, -kx));
                } else {
                    minxminusy = Math.max(minxminusy, safeDivide(a + (-kx) - 1, -kx));
                }
            }
        }

        private long safeDivide(long a, long b) {
            if (a > 0) return a / b; else return (a - b + 1) / b;
        }
    }

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        int l = in.nextInt();
        boolean[] know = new boolean[l + 1];
        long[] k = new long[l + 1];
        long[] ax = new long[l + 1];
        long[] ay = new long[l + 1];
        know[0] = true;
        know[l] = true;
        k[l] = 1;
        boolean knowP = false;
        long px = 0;
        long py = 0;
        for (int i = 0; i < n; ++i) {
            long t = in.nextLong();
            long x = in.nextLong();
            long y = in.nextLong();
            if ((x + y + t) % 2 != 0) {
                out.println("NO");
                return;
            }
            int when = (int) (t % l);
            long ck = -t / l;
            if (!know[when]) {
                know[when] = true;
                k[when] = ck;
                ax[when] = x;
                ay[when] = y;
            } else {
                if (knowP) {
                    if (k[when] * px + ax[when] != ck * px + x || Math.abs(k[when] * (double) px + ax[when] - ck * (double) px - x) > 1e62) {
                        out.println("NO");
                        return;
                    }
                    if (k[when] * py + ay[when] != ck * py + y || Math.abs(k[when] * (double) py + ay[when] - ck * (double) py - y) > 1e62) {
                        out.println("NO");
                        return;
                    }
                } else {
                    knowP = true;
                    long numx = x - ax[when];
                    long numy = y - ay[when];
                    long den = k[when] - ck;
                    if (numx % den != 0 || numy % den != 0) {
                        out.println("NO");
                        return;
                    }
                    px = numx / den;
                    py = numy / den;
                }
            }
        }

        {
            Intersector intersector = new Intersector();
            int prev = 0;
            for (int i = 1; i <= l; ++i) if (know[i]) {
                long dk = k[i] - k[prev];
                long dax = ax[i] - ax[prev];
                long day = ay[i] - ay[prev];
                for (int kx = -1; kx <= 1; kx += 2) {
                    for (int ky = -1; ky <= 1; ky += 2) {
                       intersector.update(kx * dk, ky * dk, kx * dax + ky * day - (i - prev));
                    }
                }
                prev = i;
            }
            if (knowP) {
                if (px + py < intersector.minxplusy || px + py > intersector.maxxplusy) {
                    out.println("NO");
                    return;
                }
                if (px - py < intersector.minxminusy || px - py > intersector.maxxminusy) {
                    out.println("NO");
                    return;
                }
            } else {
                if (intersector.minxplusy > intersector.maxxplusy) {
                    out.println("NO");
                    return;
                }
                if (intersector.minxminusy > intersector.maxxminusy) {
                    out.println("NO");
                    return;
                }
                long xplusy;
                if (intersector.minxplusy == Long.MIN_VALUE) {
                    if (intersector.maxxplusy == Long.MAX_VALUE) {
                        xplusy = 0;
                    } else {
                        xplusy = intersector.maxxplusy - 1;
                    }
                } else {
                    xplusy = intersector.minxplusy;
                }
                long xminusy;
                if (intersector.minxminusy == Long.MIN_VALUE) {
                    if (intersector.maxxminusy == Long.MAX_VALUE) {
                        xminusy = 0;
                    } else {
                        xminusy = intersector.maxxminusy - 1;
                    }
                } else {
                    xminusy = intersector.minxminusy;
                }
                if ((xplusy + xminusy) % 2 != 0) {
                    if (xplusy < intersector.maxxplusy) {
                        ++xplusy;
                    } else if (xminusy < intersector.maxxminusy) {
                        ++xminusy;
                    } else {
                        out.println("NO");
                        return;
                    }
                }
                px = (xplusy + xminusy) / 2;
                py = (xplusy - xminusy) / 2;
            }
        }

        int prev = 0;
        for (int i = 1; i <= l; ++i) if (know[i]) {
            long dk = k[i] - k[prev];
            long dax = ax[i] - ax[prev];
            long day = ay[i] - ay[prev];
            long dx = dk * px + dax;
            long dy = dk * py + day;
            if ((Math.abs(dx) + Math.abs(dy) > i - prev)) throw new RuntimeException();
            int extra = (int) ((i - prev - Math.abs(dx) - Math.abs(dy)));
            while (dx > 0) {
                out.print('R');
                --dx;
            }
            while (dx < 0) {
                out.print('L');
                ++dx;
            }
            while (dy > 0) {
                out.print('U');
                --dy;
            }
            while (dy < 0) {
                out.print('D');
                ++dy;
            }
            for (int j = 0; j < extra; ++j) {
                if (j % 2 == 0)
                    out.print("L");
                else
                    out.print("R");
            }
            prev = i;
        }
        out.println();
    }
}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream), 32768);
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    public long nextLong() {
        return Long.parseLong(next());
    }

}


import java.io.*;
import java.util.*;
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskE solver = new TaskE();
        solver.solve(1, in, out);
        out.flush();out.close();
    }
        static class TaskE {
          long mod=(long)(1E9)+7;
          long rpe(long a){long b=mod-2;
           long ans=1;
           while(b!=0){
            if(b%2!=0)ans=(ans*a)%mod;
            b/=2;a=a*a%mod;
           }return ans;
          }
          long i2=rpe(2);
          long f(long c){
           return c*(c-1+mod)%mod*i2%mod;
          }
          public void solve(int testNumber, InputReader in, PrintWriter out) {
           int n=in.nextInt();
           long a[]=new long[n+10];for(int i=1;i<=n-1;i++)a[i]=in.nextLong();a[0]=1;
           long c=1;long ans[]=new long[2*n-1];
           long dp[][]=new long[2][2*n-1];int t=0;
           long v[][]=new long[n+10][n+10];
           for(int i=1;i<=n-1;i++){
            v[i][i]=(a[i]-1+mod)%mod;
            for(int j=i+1;j<=n-1;j++)v[i][j]=v[i][j-1]*a[j]%mod;
           }
           for(int i=2;i<=n;i++){
            c=c*a[i-1]%mod;
            Arrays.fill(dp[t],0);
            for(int j=2;j<2*(i-1);j++){
             dp[t][j]=dp[t^1][j-1]%mod;
            }
            dp[t][1]=1;
            for(int j=0;j<2*n-1;j++)ans[j]=(ans[j]+dp[t][j]*c%mod)%mod;
            for(int j=i-1;j>=1;j--){
             dp[t][2*(i-j)]=(dp[t][2*(i-j)]+v[j][i-1])%mod;
             ans[2*(i-j)]=(ans[2*(i-j)]+c*v[j][i-1]%mod*i2%mod)%mod;
            }
            t=t^1;
           }
           /*for(int i=2;i<=n;i++){
            c=(c*a[i-1])%mod;
            for(int j=i-1;j>=1;j--){
             long m=1;
             for(int k=i-j;k<=2*(i-j);k++){
              long v=c*m%mod;if(k==2*(i-j))v=v*i2%mod;//f(a[j])*a[j-1]%mod;
              ans[k]=(ans[k]+v)%mod;
              if(k==i-j)m=m*(a[j+k-(i-j)]-1+mod)%mod;
              else m=m*a[j+k-(i-j)]%mod;
             }
            }
           }*/
           for(int i=1;i<2*n-1;i++)out.print(ans[i]+" ");
          }
         /*pair ja[][];long w[];int from[],to[],c[];
             void make(int n,int m,InputReader in){
              ja=new pair[n+1][];w=new long[m];from=new int[m];to=new int[m];c=new int[n+1];
              for(int i=0;i<m;i++){
               int u=in.nextInt(),v=in.nextInt();long wt=in.nextLong();
               c[u]++;c[v]++;from[i]=u;to[i]=v;w[i]=wt;
              }
              for(int i=1;i<=n;i++){
               ja[i]=new pair[c[i]];c[i]=0;
              }
              for(int i=0;i<m;i++){
               ja[from[i]][c[from[i]]++]=new pair(to[i],w[i]);
               ja[to[i]][c[to[i]]++]=new pair(from[i],w[i]);
              }
             }*/
        int[] radixSort(int[] f){ return radixSort(f, f.length); }
	int[] radixSort(int[] f, int n)
	{
		int[] to = new int[n];
		{
			int[] b = new int[65537];
			for(int i = 0;i < n;i++)b[1+(f[i]&0xffff)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;i++)to[b[f[i]&0xffff]++] = f[i];
			int[] d = f; f = to;to = d;
		}
		{
			int[] b = new int[65537];
			for(int i = 0;i < n;i++)b[1+(f[i]>>>16)]++;
			for(int i = 1;i <= 65536;i++)b[i]+=b[i-1];
			for(int i = 0;i < n;i++)to[b[f[i]>>>16]++] = f[i];
			int[] d = f; f = to;to = d;
		}
		return f;
	}
    }
    static class InputReader {
        BufferedReader br;
        StringTokenizer st;
        public InputReader(InputStream stream) {
            br = new BufferedReader(new InputStreamReader(stream));
            st = null;
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return null;
                st = new StringTokenizer(s);
            }
            return st.nextToken();
        }

        boolean hasMoreTokens() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return false;
                st = new StringTokenizer(s);
            }
            return true;
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
            return Long.parseLong(next());
        }
        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}

// practice with rainboy
// https://codeforces.com/blog/entry/58519
import java.io.*;
import java.util.*;

public class CF954H extends PrintWriter {
	CF954H() { super(System.out, true); }
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF954H o = new CF954H(); o.main(); o.flush();
	}

	static final int MD = 1000000007, INV2 = 500000004;
	int d_, x_, y_;
	void gcd_(int a, int b) {
		if (b == 0) {
			d_ = a; x_ = 1; y_ = 0;
		} else {
			gcd_(b, a % b);
			int t = x_ - a / b * y_; x_ = y_; y_ = t;
		}
	}
	int inv(int a) {
		gcd_(a, MD);
		return x_;
	}
	void main() {
		int n = sc.nextInt();
		int[] aa = new int[n - 1];
		for (int h = 0; h < n - 1; h++)
			aa[h] = sc.nextInt();
		int[] pp = new int[n], pp_ = new int[n];
		pp[n - 1] = pp_[n - 1] = 1;
		for (int h = n - 2; h >= 0; h--)
			pp_[h] = inv(pp[h] = (int) ((long) aa[h] * pp[h + 1] % MD));
		int[][] qq = new int[n][n * 2];
		for (int h = 0; h < n; h++)
			qq[h][0] = 1;
		for (int k = 1; k < n * 2; k++)
			for (int h = 1; h < n; h++) {
				long x = qq[h - 1][k - 1];
				if (k >= 2 && h + k - 2 < n) {
					long p = (long) pp[h] * pp_[h + k - 2] % MD;
					x = (x + (aa[h - 1] - 1) * p) % MD;
				}
				qq[h][k] = (int) x;
			}
		for (int k = 1; k < n * 2 - 1; k++) {
			long x = 0;
			for (int h = 0; h < n; h++) {
				long cnt = (long) pp[0] * pp_[h] % MD;
				long p = h + k < n ? (long) pp[h] * pp_[h + k] % MD : 0;
				long q = qq[h][k];
				x = (x + (long) cnt * (p + q)) % MD;
			}
			x = x * INV2 % MD;
			if (x < 0)
				x += MD;
			print(x + " ");
		}
		println();
	}
}

import java.io.*;
import java.util.*;

public class A {
	public static void main (String[] args) { new A(); }

	int MOD = (int)1e9+7;

	public A() {
		FastScanner fs = new FastScanner();
		PrintWriter out = new PrintWriter(System.out);
		System.err.println("");

		int n = fs.nextInt();
		int[] kids = new int[n];
		for(int i = 0; i < n-1; i++) kids[i] = fs.nextInt();

		int[][] walkDown = new int[n][n];
		int[][] walkDown2 = new int[n][n];

		for(int i = 0; i < n; i++) {
			int prod = 1, prod2 = 1;
			for(int j = 1; j < n; j++) {
				if(i + j - 1 >= n) break;

				if(j == 1) prod2 = mult(prod2, Math.max(0, kids[i + j - 1] - 1));
				else prod2 = mult(prod2, kids[i + j - 1]);

				prod = mult(prod, kids[i + j - 1]);

				walkDown[i][j] = prod;
				walkDown2[i][j] = prod2;
			}
		}

		for(int j = 0; j < n; j++) {
			for(int d = 1; ; d++) {
				int row = 0+d;
				int col = j+d;
				if(row >= n || col >= n) break;

				walkDown2[row][col] = add(walkDown2[row][col], walkDown2[row-1][col-1]);
			}
		}
		for(int i = 1; i < n; i++) {
			for(int d = 1; ; d++) {
				int row = i+d;
				int col = 0+d;
				if(row >= n || col >= n) break;

				walkDown2[row][col] = add(walkDown2[row][col], walkDown2[row-1][col-1]);
			}
		}

		int[] freq = new int[n];
		freq[0] = 1;
		for(int i = 1; i < n; i++) {
			freq[i] = mult(freq[i-1], kids[i-1]);
		}

		int[] totWays = new int[2 * n];

		for(int kid = n-1; kid >= 0; kid--) {
			for(int dist = 1; dist <= 2 * n - 2; dist++) {
				int tot = 0;

				if(dist < n) tot = add(tot, walkDown[kid][dist]);

				if(kid > 0) {
					int row = kid-1, col = dist-1;
					if(row >= n || col >= n) {
						int d = Math.max(row-n+1, col-n+1);
						row -= d;
						col -= d;
					}
					int finRow = kid-dist, finCol = 0;
					if(finRow < 0) {
						int add = -finRow;
						finRow += add;
						finCol += add;
					}

					if(row >= finRow) {
						int x = walkDown2[row][col];
						if(finRow > 0 && finCol > 0) {
							x -= walkDown2[finRow-1][finCol-1];
						}
						tot = add(tot, x);
					}
				}

//				System.out.println(kid + " " + dist + " " + tot);
				if(kid-dist >= 0) tot = add(tot, 1);

				totWays[dist] = add(totWays[dist], mult(tot, freq[kid]));
			}
//			System.out.println();
		}

		int INV2 = (MOD+1)/2;

		for(int i = 0; i < totWays.length; i++) {
			totWays[i] = mult(totWays[i], INV2);
		}

		for(int i = 1; i <= 2 * n - 2; i++) {
			if(i > 1) out.print(" ");
			out.print(totWays[i]);
		}
		out.println();

		out.close();
	}

	int add(int a, int b) {
		a += b;
		if(a >= MOD) a -= MOD;
		return a;
	}

	int mult(long a, long b) {
		return (int)(a * b % MOD);
	}

	class FastScanner {
		public int BS = 1<<16;
		public char NC = (char)0;
		byte[] buf = new byte[BS];
		int bId = 0, size = 0;
		char c = NC;
		double num = 1;
		BufferedInputStream in;

		public FastScanner() {
			in = new BufferedInputStream(System.in, BS);
		}

		public FastScanner(String s) {
			try {
				in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
			}
			catch (Exception e) {
				in = new BufferedInputStream(System.in, BS);
			}
		}

		public char nextChar(){
			while(bId==size) {
				try {
					size = in.read(buf);
				}catch(Exception e) {
					return NC;
				}
				if(size==-1)return NC;
				bId=0;
			}
			return (char)buf[bId++];
		}

		public int nextInt() {
			return (int)nextLong();
		}

		public long nextLong() {
			num=1;
			boolean neg = false;
			if(c==NC)c=nextChar();
			for(;(c<'0' || c>'9'); c = nextChar()) {
				if(c=='-')neg=true;
			}
			long res = 0;
			for(; c>='0' && c <='9'; c=nextChar()) {
				res = (res<<3)+(res<<1)+c-'0';
				num*=10;
			}
			return neg?-res:res;
		}

		public double nextDouble() {
			double cur = nextLong();
			return c!='.' ? cur:cur+nextLong()/num;
		}

		public String next() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c>32) {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public String nextLine() {
			StringBuilder res = new StringBuilder();
			while(c<=32)c=nextChar();
			while(c!='\n') {
				res.append(c);
				c=nextChar();
			}
			return res.toString();
		}

		public boolean hasNext() {
			if(c>32)return true;
			while(true) {
				c=nextChar();
				if(c==NC)return false;
				else if(c>32)return true;
			}
		}

		public int[] nextIntArray(int n) {
			int[] res = new int[n];
			for(int i = 0; i < n; i++) res[i] = nextInt();
			return res;
		}

	}

}

import java.io.*;

/**
 * Created by dalt on 2018/4/2.
 */
public class CF954H {
    public static final int MOD = (int) (1e9 + 7);
    public static BlockReader input;
    public static PrintStream output;

    public static void main(String[] args) throws FileNotFoundException {
        if (System.getProperty("ONLINE_JUDGE") == null) {
            input = new BlockReader(new FileInputStream("D:\\DataBase\\TESTCASE\\codeforces\\CF954H.in"));
            output = System.out;
        } else {
            input = new BlockReader(System.in);
            output = new PrintStream(new BufferedOutputStream(System.out), false);
        }

        solve();

        output.flush();
    }

    public static void solve() {
        int n = input.nextInteger();
        long[] a = new long[n];
        long[] aRev = new long[n];
        long[] aChoose2Child = new long[n + 1];
        long[] aChoose2ChildRev = new long[n + 1];
        long negTwo = pow(2, MOD - 2);
        for (int i = 0, until = n - 1; i < until; i++) {
            a[i] = input.nextInteger();
            aRev[i] = pow(a[i], MOD - 2);
        }

        for (int i = 0; i < n; i++) {
            aChoose2Child[i] = a[i] * (a[i] - 1) % MOD;
            aChoose2ChildRev[i] = pow( aChoose2Child[i], MOD - 2);
        }

        long[] prefixMul = new long[n];
        long[] prefixRev = new long[n];
        prefixMul[0] = 1;
        prefixRev[0] = 1;
        for (int i = 1; i < n; i++) {
            prefixMul[i] = prefixMul[i - 1] * a[i - 1] % MOD;
            prefixRev[i] = prefixRev[i - 1] * aRev[i - 1] % MOD;
        }

        int m = (n - 1) * 2;
        long[] f = new long[m + 1];
        Loop<long[][]> dpLoop = new Loop<>(new long[m + 1][3], new long[m + 1][3]);
        final int ROTATE = 0;
        final int BALANCE = 2;
        final int LINE = 1;

        {
            long[][] next = dpLoop.turn();
            next[0][BALANCE] = 1;
        }
        for (int i = n - 2; i >= 0; i--) {
            long[][] former = dpLoop.get(0);
            long[][] next = dpLoop.turn();

            long aChooseRev = aChoose2ChildRev[i + 1] * a[i + 1] % MOD * a[i + 1] % MOD * aChoose2Child[i] % MOD;
            for (int j = 2, until = ((n - 1) - i) * 2; j <= until; j++) {
                next[j][ROTATE] = (former[j - 2][ROTATE] * aChooseRev % MOD + former[j - 2][LINE] * aChoose2Child[i] % MOD) % MOD;

                int halfJ = j >> 1;
                if ((j & 1) == 0 && i + halfJ < n) {
                    long possible = prefixMul[i + halfJ] * prefixRev[i + 1] % MOD;
                    possible = possible * possible % MOD;
                    next[j][BALANCE] = possible * aChoose2Child[i]  % MOD * negTwo % MOD;
                } else {
                    next[j][BALANCE] = 0;
                }

                if (i + j < n) {
                    next[j][LINE] = prefixMul[i + j] * prefixRev[i] % MOD;
                } else {
                    next[j][LINE] = 0;
                }
            }

            next[2][BALANCE] = aChoose2Child[i] * negTwo % MOD;
            next[1][LINE] = a[i];
            next[0][BALANCE] = 1;

            for (int j = 1; j <= m; j++) {
                f[j] = (f[j] + (next[j][LINE] + next[j][ROTATE] + next[j][BALANCE]) * prefixMul[i]) % MOD;
            }
        }

        for (int i = 1; i <= m; i++) {
            output.print(f[i]);
            output.print(' ');
        }
    }

    public static long pow(long x, int n) {
        int bit = 31 - Integer.numberOfLeadingZeros(n);
        long product = 1;
        for (; bit >= 0; bit--) {
            product = product * product % MOD;
            if (((1 << bit) & n) != 0) {
                product = product * x % MOD;
            }
        }
        return product;
    }

    public static class Loop<T> {
        T[] data;
        int offset;

        public Loop(T... data) {
            this.data = data;
        }

        public T turn() {
            offset++;
            return get(0);
        }

        public T get(int index) {
            return data[(index + offset) % data.length];
        }
    }

    public static class BlockReader {
        static final int EOF = -1;
        InputStream is;
        byte[] dBuf;
        int dPos, dSize, next;
        StringBuilder builder = new StringBuilder();

        public BlockReader(InputStream is) {
            this(is, 4096);
        }

        public BlockReader(InputStream is, int bufSize) {
            this.is = is;
            dBuf = new byte[bufSize];
            next = nextByte();
        }

        public int nextByte() {
            while (dPos >= dSize) {
                if (dSize == -1) {
                    return EOF;
                }
                dPos = 0;
                try {
                    dSize = is.read(dBuf);
                } catch (Exception e) {
                }
            }
            return dBuf[dPos++];
        }

        public String nextBlock() {
            builder.setLength(0);
            skipBlank();
            while (next != EOF && !Character.isWhitespace(next)) {
                builder.append((char) next);
                next = nextByte();
            }
            return builder.toString();
        }

        public void skipBlank() {
            while (Character.isWhitespace(next)) {
                next = nextByte();
            }
        }

        public int nextInteger() {
            skipBlank();
            int ret = 0;
            boolean rev = false;
            if (next == '+' || next == '-') {
                rev = next == '-';
                next = nextByte();
            }
            while (next >= '0' && next <= '9') {
                ret = (ret << 3) + (ret << 1) + next - '0';
                next = nextByte();
            }
            return rev ? -ret : ret;
        }

        public int nextBlock(char[] data, int offset) {
            skipBlank();
            int index = offset;
            int bound = data.length;
            while (next != EOF && index < bound && !Character.isWhitespace(next)) {
                data[index++] = (char) next;
                next = nextByte();
            }
            return index - offset;
        }

        public boolean hasMore() {
            skipBlank();
            return next != EOF;
        }
    }
}

import java.util.Scanner;

public class Main {
    private static final int P = 1000000007;
    private static long pow(long x, int y) {
        long ret = 1;
        while (y > 0) {
            if (y %2 == 1) {
                ret = ret * x % P;
            }
            x = x * x % P;
            y /= 2;
        }
        return ret;
    }
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        int n = cin.nextInt();
        int[] a = new int[n + 1];
        long[] rev = new long[n + 1];
        long[] res = new long[2 * n + 1];
        long[][] down = new long[n + 1][n + 1];
        long[][] up = new long[2][2 * n + 1];
        for (int i = 1; i < n; ++i) {
            a[i] = cin.nextInt();
            rev[i] = pow(a[i], P - 2);
        }
        for (int i = n; i > 0; --i) {
            down[i][0] = 1;
            for (int j = 1; j < n; ++j) {
                if (i + j > n) {
                    break;
                }
                down[i][j] = down[i + 1][j - 1] * a[i] % P;
            }
        }

        long number = 1;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                res[j] = (res[j] + number * down[i][j] % P) % P;
            }
            number = (number * a[i]) % P;
        }
        int pre = 0;
        number = a[1];
        for (int i = 2; i <= n; ++i) {
            int now = 1 - pre;
            for (int j = 0; j <= 2 * n - 2; ++j) {
                up[now][j] = 0;
            }
            up[now][1] = 1;
            for (int j = 2; j <= 2 * n - 2; ++j) {
                if (j - 1 <= n) {
                    up[now][j] = (up[pre][j - 1] + down[i - 1][j - 1] * rev[i - 1] % P * (a[i - 1] - 1) % P) % P;
                } else {
                    up[now][j] = up[pre][j - 1];
                }
            }
            for (int j = 1; j <= 2 * n - 2; ++j) {
                res[j] = (res[j] + number * up[now][j]  % P) % P;
            }
            number = (number * a[i]) % P;
            pre = now;
        }
        for (int i = 1; i <= 2 * n - 2; ++i) {
            System.out.print(res[i] * pow(2, P - 2) % P + " ");
        }
    }
}