Problem:
Score : 400 points

Problem Statement

In some other world, today is Christmas.

Mr. Takaha decides to make a multi-dimensional burger in his party. A level-L burger (L is an integer greater than or equal to 0) is the following thing:

A level-0 burger is a patty.

A level-L burger (L \geq 1) is a bun, a level-(L-1) burger, a patty, another level-(L-1) burger and another bun, stacked vertically in this order from the bottom.

For example, a level-1 burger and a level-2 burger look like BPPPB and BBPPPBPBPPPBB (rotated 90 degrees), where B and P stands for a bun and a patty.

The burger Mr. Takaha will make is a level-N burger. Lunlun the Dachshund will eat X layers from the bottom of this burger (a layer is a patty or a bun). How many patties will she eat?

Constraints

1 \leq N \leq 50

1 \leq X \leq ( the total number of layers in a level-N burger )

N and X are integers.

Input

Input is given from Standard Input in the following format:

N X

Output

Print the number of patties in the bottom-most X layers from the bottom of a level-N burger.

Sample Input 1

2 7

Sample Output 1

4

There are 4 patties in the bottom-most 7 layers of a level-2 burger (BBPPPBPBPPPBB).

Sample Input 2

1 1

Sample Output 2

0

The bottom-most layer of a level-1 burger is a bun.

Sample Input 3

50 4321098765432109

Sample Output 3

2160549382716056

A level-50 burger is rather thick, to the extent that the number of its layers does not fit into a 32-bit integer.

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


import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {

        //		ABC115_A();
        //		ABC115_B();
        //		ABC115_C();
        ABC115_D();
    }

    private static void ABC115_A() {
        Scanner scanner = null;
        int date = 0;

        try {
            scanner = new Scanner(System.in);
            date = scanner.nextInt();

            switch (date) {
                case 22:
                    System.out.println("Christmas Eve Eve Eve");
                    break;
                case 23:
                    System.out.println("Christmas Eve Eve");
                    break;
                case 24:
                    System.out.println("Christmas Eve");
                    break;
                case 25:
                    System.out.println("Christmas");
                    break;
                default:
                    System.out.println("fail!");
                    break;
            }

        } finally {
            if (scanner != null) {
                scanner.close();
            }
        }
    }

    private static void ABC115_B() {
        Scanner scanner = null;
        int numItem = 0;

        try {
            scanner = new Scanner(System.in);
            numItem = scanner.nextInt();
            int[] priceArray = new int[numItem];

            for (int i = 0; i < numItem; i++) {
                priceArray[i] = scanner.nextInt();
            }

            Arrays.sort(priceArray);

            int prices = 0;
            for (int i = 0; i < priceArray.length; i++) {
                if (i != numItem - 1) {
                    prices += priceArray[i];
                } else {
                    prices += priceArray[i] / 2;
                }

            }

            System.out.println(prices);

        } finally {
            if (scanner != null) {
                scanner.close();
            }
        }
    }

    private static void ABC115_C() {
        Scanner scanner = null;
        //totalTreeNum
        int numN = 0;
        //selectedTreeNum
        int numK = 0;

        try {
            scanner = new Scanner(System.in);
            numN = scanner.nextInt();
            numK = scanner.nextInt();

            int[] treeHeightList = new int[numN];

            for (int i = 0; i < numN; i++) {
                treeHeightList[i] = scanner.nextInt();
            }

            Arrays.sort(treeHeightList);

            int minDiff = 0;
            for (int i = 0; i < treeHeightList.length - (numK - 1); i++) {
                if (i == 0) {
                    minDiff = treeHeightList[i + numK - 1] - treeHeightList[i];
                }
                if (minDiff > treeHeightList[i + numK - 1] - treeHeightList[i]) {
                    minDiff = treeHeightList[i + numK - 1] - treeHeightList[i];
                }

            }
            System.out.println(minDiff);

        } finally {
            if (scanner != null) {
                scanner.close();
            }
        }
    }

    private static void ABC115_D() {
        Scanner scanner = null;
        int burgerLevel = 0;
        long biteNum = 0;

        try {
            scanner = new Scanner(System.in);
            burgerLevel = scanner.nextInt();
            biteNum = scanner.nextLong();

            /*
             * TLE
             */
//            List<Integer> baseBurger = getBite(burgerLevel);
//            long res = 0;
//            int n = baseBurger.size() - 1;
//            for (int i = 0; i < biteNum; i++) {
//                if (baseBurger.get(n - i) == 1)
//                    res++;
//            }
//            System.out.println(res);

            long[] all = new long[burgerLevel + 1];
            all[0] = 1;
            long[] patty = new long[burgerLevel + 1];
            patty[0] = 1;
            for (int i = 1; i <= burgerLevel; i++) {
                all[i] = all[i - 1] * 2L + 3L;
                patty[i] = patty[i - 1] * 2L + 1L;
            }
            System.out.println(getBite(all, patty, burgerLevel, biteNum));
        } finally {
            if (scanner != null) {
                scanner.close();
            }
        }
    }

    private static long getBite(long[] all, long[] patty, int level, long x) {
        if (level == 0)
            return 1;

        if (x == 1)
            return 0;
        //1個前のバーガー+バンズより小さい=バンズ1個食べて再帰
        if (x < all[level - 1] + 1)
            return getBite(all, patty, level - 1, x - 1);

        //1個前のバーガー+バンズと同じ=1個前のパティと同じ
        if (x == all[level - 1] + 1)
            return patty[level - 1];
        //1個前のバーガー+バンズ+パティと同じ=1個前のパティ+真ん中のパティ
        if (x == all[level - 1] + 2)
            return patty[level - 1] + 1;
        /*
        1個前のバーガー+バンズ+パティより大きい=1個前のパティ+真ん中のパティ+残り
        （ただし、バイト数は一番前のバンズと真ん中のパティ分はかんだこととする）
         */
        if (x > all[level - 1] + 2)
            return patty[level - 1] + 1 + getBite(all, patty, level - 1, x - (all[level - 1] + 2));

        return -1;
    }

    private static List<Integer> getBite(long level) {
        List<Integer> res = new ArrayList<Integer>();
        if (level == 0) {
            res.add(1);
            return res;
        }
        res.add(0);
        res.addAll(getBite(level - 1));
        res.add(1);
        res.addAll(getBite(level - 1));
        res.add(0);
        return res;
    }

}