Problem:
Score : 2300 points

Problem Statement

You are given a set S of strings consisting of 0 and 1, and an integer K.

Find the longest string that is a subsequence of K or more different strings in S.
If there are multiple strings that satisfy this condition, find the lexicographically smallest such string.

Here, S is given in the format below:

The data directly given to you is an integer N, and N+1 strings X_0,X_1,...,X_N. For every i (0\leq i\leq N), the length of X_i is 2^i.

For every pair of two integers (i,j) (0\leq i\leq N,0\leq j\leq 2^i-1), the j-th character of X_i is 1 if and only if the binary representation of j with i digits (possibly with leading zeros) belongs to S. Here, the first and last characters in X_i are called the 0-th and (2^i-1)-th characters, respectively.

S does not contain a string with length N+1 or more.

Here, a string A is a subsequence of another string B when there exists a sequence of integers t_1 < ... < t_{|A|} such that, for every i (1\leq i\leq |A|), the i-th character of A and the t_i-th character of B is equal.

Constraints

0 \leq N \leq 20

X_i(0\leq i\leq N) is a string of length 2^i consisting of 0 and 1.

1 \leq K \leq |S|

K is an integer.

Input

Input is given from Standard Input in the following format:

N K
X_0
:
X_N

Output

Print the lexicographically smallest string among the longest strings that are subsequences of K or more different strings in S.

Sample Input 1

3 4
1
01
1011
01001110

Sample Output 1

10

The following strings belong to S: the empty string, 1, 00, 10, 11, 001, 100, 101 and 110.
The lexicographically smallest string among the longest strings that are subsequences of four or more of them is 10.

Sample Input 2

4 6
1
01
1011
10111010
1101110011111101

Sample Output 2

100

Sample Input 3

2 5
0
11
1111

Sample Output 3

The answer is the empty string.

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Accepted)

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

public class Main {
    FastScanner in;
    PrintWriter out;

    String toStr(int mask) {
        return Integer.toBinaryString(mask).substring(1);
    }

    void solve() {
        int n = in.nextInt();
        int k = in.nextInt();
        int[][] dp = new int[1 << (n + 1)][];
        for (int rmask = 1; rmask < dp.length; rmask++) {
            int len = n - (32 - Integer.numberOfLeadingZeros(rmask)) + 2;
            dp[rmask] = new int[1 << len];
        }
        for (int i = 0; i <= n; i++) {
            char[] s = in.next().toCharArray();
            for (int mask = 0; mask < s.length; mask++) {
                if (s[mask] == '1') {
                    int set = mask + s.length;
                    dp[1][set]++;
                }
            }
        }
        String ans= "";
        for (int rmask = 1; rmask < dp.length; rmask++) {
            int[] curDp = dp[rmask];
            int sum = 0;
            for (int s : curDp) {
                sum += s;
            }
            if (sum < k) {
                continue;
            }
            String cur = toStr(rmask);
            if (cur.length() > ans.length() || cur.compareTo(ans) < 0) {
                ans= cur;
            }
            for (int curMoreMask = 2; curMoreMask < dp[rmask].length; curMoreMask++) {
                int cnt = curDp[curMoreMask];
                if (cnt == 0) {
                    continue;
                }
                int highestBit = 31 - Integer.numberOfLeadingZeros(curMoreMask);
                int nowBit = (curMoreMask >> (highestBit - 1)) & 1;
                int nextMask = curMoreMask & ((1 << highestBit) - 1);
                nextMask |= (1 << (highestBit - 1));
                int tmp = (rmask << 1) | nowBit;
                dp[tmp][nextMask] += cnt;
                nextMask = getNextNotMask(curMoreMask);
                if (nextMask != -1) {
                    tmp = (rmask << 1) | (1 - nowBit);
                    dp[tmp][nextMask] += cnt;
                }
            }
        }
        out.println(ans);
    }

    int getNextNotMask(int mask) {
        int highestBit = 31 - Integer.numberOfLeadingZeros(mask);
        int needBit = 1 - ((mask >> (highestBit - 1)) & 1);
        for (int bit = highestBit - 2; bit >= 0; bit--) {
            int curBit = (mask >> bit) & 1;
            if (curBit == needBit) {
                return (mask & ((1 << bit) - 1)) | (1 << bit);
            }
        }
        return -1;
    }

    void run() {
        try {
            in = new FastScanner(new File("Main.in"));
            out = new PrintWriter(new File("Main.out"));

            solve();

            out.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    void runIO() {

        in = new FastScanner(System.in);
        out = new PrintWriter(System.out);

        solve();

        out.close();
    }

    class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(File f) {
            try {
                br = new BufferedReader(new FileReader(f));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        public FastScanner(InputStream f) {
            br = new BufferedReader(new InputStreamReader(f));
        }

        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;
        }

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

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

        double nextDouble() {
            return Double.parseDouble(next());
        }
    }

    public static void main(String[] args) {
        new Main().runIO();
    }
}