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 C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

class Program
{
    public Program() { }


    Scanner cin;

    long[] All;
    long[] Pate;

    void myon()
    {
        cin = new Scanner();
        int N = cin.nextInt();
        long X = cin.nextLong();

        int MaxN = 51;
        All = new long[MaxN];
        Pate = new long[MaxN];

        All[0] = 1;
        Pate[0] = 1;
        for (int i = 1; i < MaxN; i++)
        {
            All[i] = All[i - 1] * 2 + 3;
            Pate[i] = Pate[i - 1] * 2 + 1;
        }

        Console.WriteLine(dfs(N, X));
    }

    long dfs(int Level, long Remain)
    {
        if(Level == 0)
        {
            return 1;
        }

        long ans = 0;
        //最初のバン
        if (Remain >= 1)
        {
            Remain--;
        }
        //Level X-1
        if(Remain >= 1)
        {
            //レベルX-1バーガーを全部食べれる時は、全部同時にカウントしてしまう
            if(Remain >= All[Level - 1])
            {
                Remain -= All[Level - 1];
                ans += Pate[Level - 1];
            }
            else
            {
                ans += dfs(Level - 1, Remain);
                Remain = 0;
            }

        }

        //パティ
        if (Remain >= 1)
        {
            Remain--;
            ans++;
        }

        //Level X-1

        if (Remain >= 1)
        {
            //レベルX-1バーガーを全部食べれる時は、全部同時にカウントしてしまう
            if (Remain >= All[Level - 1])
            {
                Remain -= All[Level - 1];
                ans += Pate[Level - 1];
            }
            else
            {
                ans += dfs(Level - 1, Remain);
                Remain = 0;
            }

        }

        //バン
        if (Remain >= 1)
        {
            Remain--;
        }

        return ans;
    }

    static void Main(string[] args)
    {
        new Program().myon();
    }
}


class Scanner
{
    string[] s;
    int i;

    char[] cs = new char[] { ' ' };

    public Scanner()
    {
        s = new string[0];
        i = 0;
    }

    public string next()
    {
        if (i < s.Length) return s[i++];
        string st = Console.ReadLine();
        while (st == "") st = Console.ReadLine();
        s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
        i = 0;
        return next();
    }

    public int nextInt()
    {
        return int.Parse(next());
    }

    public long nextLong()
    {
        return long.Parse(next());
    }

    public double nextDouble()
    {
        return double.Parse(next());
    }

}