import java.io.OutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.util.StringTokenizer; import java.io.Writer; import java.io.OutputStreamWriter; import java.io.BufferedReader; import java.io.InputStream; /** * Built using CHelper plug-in * Actual solution is at the top * * @author lewin */ public class leaderboard_lewin { public static void main(String[] args) { InputStream inputStream = System.in; OutputStream outputStream = System.out; InputReader2 in = new InputReader2(inputStream); OutputWriter out = new OutputWriter(outputStream); LeaderboardEffect solver = new LeaderboardEffect(); solver.solve(1, in, out); out.close(); } static class LeaderboardEffect { public void solve(int testNumber, InputReader2 in, OutputWriter out) { int n = in.nextInt(), t = in.nextInt(); int[] r = new int[n], c = new int[n]; double[] p = new double[n]; for (int i = 0; i < n; i++) { r[i] = in.nextInt(); c[i] = in.nextInt(); p[i] = in.nextDouble(); } double[] probSolve = new double[n]; double[][] toAdd = new double[t + 1][n]; // probSolve[i] = fraction of teams that have currently solved problem i // toAdd[i][j] = fraction of teams that will solve problem j at time i double[][] numTeams = new double[t + 1][1 << n]; // numTeams[i][j] = fraction of teams who will need to read a problem at time i with mask j already read numTeams[0][0] = 1; for (int time = 0; time <= t; time++) { // process all teams solving problems for (int problem = 0; problem < n; problem++) { probSolve[problem] += toAdd[time][problem]; } // process teams deciding which problem to solve for (int mask = 0; mask < (1 << n); mask++) { if (numTeams[time][mask] == 0) continue; double totalSolve = 0; int numUnread = 0; for (int i = 0; i < n; i++) { if (((mask >> i) & 1) == 1) continue; totalSolve += probSolve[i]; numUnread++; } for (int i = 0; i < n; i++) { if (((mask >> i) & 1) == 1) continue; double probChosen = totalSolve == 0 ? (1.0 / numUnread) : (probSolve[i] / totalSolve); int ntime; { // this team can solve this problem ntime = r[i] + c[i] + time; if (p[i] > 0 && ntime <= t) { toAdd[ntime][i] += numTeams[time][mask] * probChosen * p[i]; numTeams[ntime][mask | (1 << i)] += numTeams[time][mask] * probChosen * p[i]; } } { // this team can't solve this problem ntime = r[i] + time; if (p[i] < 1 && ntime <= t) { numTeams[ntime][mask | (1 << i)] += numTeams[time][mask] * probChosen * (1 - p[i]); } } } } } for (int i = 0; i < n; i++) { out.printf("%.10f\n", probSolve[i]); } } } static class OutputWriter { private final PrintWriter writer; public OutputWriter(OutputStream outputStream) { writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream))); } public OutputWriter(Writer writer) { this.writer = new PrintWriter(writer); } public void printf(String format, Object... objects) { writer.printf(format, objects); } public void close() { writer.close(); } } static class InputReader2 { private BufferedReader in; private StringTokenizer st; public InputReader2(InputStream stream) { in = new BufferedReader(new InputStreamReader(stream)); st = null; } public int nextInt() { return Integer.parseInt(next()); } public double nextDouble() { return Double.parseDouble(next()); } public String next() { while (st == null || !st.hasMoreTokens()) { try { st = new StringTokenizer(in.readLine()); } catch (IOException e) { e.printStackTrace(); } } return st.nextToken(); } } }