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

namespace CodeForces
{
    class Program
    {
        private static void Unary()
        {
            //take the input
            string input = Console.ReadLine();
            StringBuilder Binput = new StringBuilder();
            //use the table to get the values
            foreach (char c in input)
            {
                switch (c)
                {
                    case '>':
                        Binput.Append("1000");
                        break;
                    case '<':
                        Binput.Append("1001");
                        break;
                    case '+':
                        Binput.Append("1010");
                        break;
                    case '-':
                        Binput.Append("1011");
                        break;
                    case '.':
                        Binput.Append("1100");
                        break;
                    case ',':
                        Binput.Append("1101");
                        break;
                    case '[':
                        Binput.Append("1110");
                        break;
                    case ']':
                        Binput.Append("1111");
                        break;
                    default:
                        Console.WriteLine("Wrong Token Entered");
                        break;
                }
            }
            //convert to Decimal value
            long output = toDecimal(Binput.ToString());
            output %= 100003;
            Console.WriteLine(output);
        }
        static private long toDecimal(string s)
        {
            long value=0;
            for (int i = 0; i < s.Length; i++)
            {
                value += Convert.ToUInt32(s[i]-'0') * (long)Math.Pow(2, s.Length - i-1);
            }

            return value;
        }
        static void Main(string[] args)
        {
            Unary();
        }
    }
}


using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
using Debug = System.Diagnostics.Debug;
using StringBuilder = System.Text.StringBuilder;
using System.Numerics;
using Point = System.Numerics.Complex;
using Number = System.Int64;
namespace Program
{
    public class Solver
    {
        public void Solve()
        {
            var n = sc.Long();
            var k = sc.Long();
            var l = sc.Integer();
            ModInteger.Mod = sc.Long();
            ModInteger ans = 1;
            if ((1L << Math.Min(63, l)) <= k) ans = 0;
            for (int i = 0; i < l; i++)
            {
                var mat = new ModMatrix(4, 4);
                mat[0, 0] = mat[0, 1] = mat[0, 2] = 1;
                mat[1, 0] = mat[1, 1] = 1;
                mat[2, 3] = 1;
                mat[3, 2] = mat[3, 3] = 1;
                var res = ModMatrix.Pow(mat, n);
                var vec = new ModMatrix(4, 1);
                vec[3, 0] = 1;
                var C = res * vec;
                var mul = C[2, 0] + C[3, 0];
                if ((k >> i & 1) == 1)
                    mul = ModInteger.Pow(2, n) - mul;
                ans *= mul;
                Debug.WriteLine(C[2, 0] + C[3, 0]);

            }
            IO.Printer.Out.WriteLine(ans);
        }
        public IO.StreamScanner sc = new IO.StreamScanner(Console.OpenStandardInput());
        static T[] Enumerate<T>(int n, Func<int, T> f) { var a = new T[n]; for (int i = 0; i < n; ++i) a[i] = f(i); return a; }
        static public void Swap<T>(ref T a, ref T b) { var tmp = a; a = b; b = tmp; }

    }
}
#region main
static class Ex
{
    static public string AsString(this IEnumerable<char> ie) { return new string(System.Linq.Enumerable.ToArray(ie)); }
    static public string AsJoinedString<T>(this IEnumerable<T> ie, string st = " ") { return string.Join(st, ie); }
    static public void Main()
    {
        var solver = new Program.Solver();
        solver.Solve();
        Program.IO.Printer.Out.Flush();
    }
}
#endregion
#region Ex
namespace Program.IO
{
    using System.IO;
    using System.Text;
    using System.Globalization;
    public class Printer : StreamWriter
    {
        static Printer() { Out = new Printer(Console.OpenStandardOutput()) { AutoFlush = false }; }
        public static Printer Out { get; set; }
        public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
        public Printer(System.IO.Stream stream) : base(stream, new UTF8Encoding(false, true)) { }
        public Printer(System.IO.Stream stream, Encoding encoding) : base(stream, encoding) { }
        public void Write<T>(string format, T[] source) { base.Write(format, source.OfType<object>().ToArray()); }
        public void WriteLine<T>(string format, T[] source) { base.WriteLine(format, source.OfType<object>().ToArray()); }
    }
    public class StreamScanner
    {
        public StreamScanner(Stream stream) { str = stream; }
        public readonly Stream str;
        private readonly byte[] buf = new byte[1024];
        private int len, ptr;
        public bool isEof = false;
        public bool IsEndOfStream { get { return isEof; } }
        private byte read()
        {
            if (isEof) return 0;
            if (ptr >= len) { ptr = 0; if ((len = str.Read(buf, 0, 1024)) <= 0) { isEof = true; return 0; } }
            return buf[ptr++];
        }
        public char Char() { byte b = 0; do b = read(); while ((b < 33 || 126 < b) && !isEof); return (char)b; }

        public string Scan()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
                sb.Append(b);
            return sb.ToString();
        }
        public string ScanLine()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b != '\n'; b = (char)read())
                if (b == 0) break;
                else if (b != '\r') sb.Append(b);
            return sb.ToString();
        }
        public long Long()
        {
            if (isEof) return long.MinValue;
            long ret = 0; byte b = 0; var ng = false;
            do b = read();
            while (b != 0 && b != '-' && (b < '0' || '9' < b));
            if (b == 0) return long.MinValue;
            if (b == '-') { ng = true; b = read(); }
            for (; true; b = read())
            {
                if (b < '0' || '9' < b)
                    return ng ? -ret : ret;
                else ret = ret * 10 + b - '0';
            }
        }
        public int Integer() { return (isEof) ? int.MinValue : (int)Long(); }
        public double Double() { var s = Scan(); return s != "" ? double.Parse(s, CultureInfo.InvariantCulture) : double.NaN; }
        private T[] enumerate<T>(int n, Func<T> f)
        {
            var a = new T[n];
            for (int i = 0; i < n; ++i) a[i] = f();
            return a;
        }

        public char[] Char(int n) { return enumerate(n, Char); }
        public string[] Scan(int n) { return enumerate(n, Scan); }
        public double[] Double(int n) { return enumerate(n, Double); }
        public int[] Integer(int n) { return enumerate(n, Integer); }
        public long[] Long(int n) { return enumerate(n, Long); }
    }
}
#endregion
#region Compair
static public class Pair
{
    static public Pair<FT, ST> Create<FT, ST>(FT f, ST s)
        where FT : IComparable<FT>
        where ST : IComparable<ST>
    { return new Pair<FT, ST>(f, s); }
    static public Pair<FT, ST> Min<FT, ST>(Pair<FT, ST> p, Pair<FT, ST> q)
        where FT : IComparable<FT>
        where ST : IComparable<ST>
    { return (p.CompareTo(q) <= 0) ? p : q; }
    static public Pair<FT, ST> Max<FT, ST>(Pair<FT, ST> p, Pair<FT, ST> q)
        where FT : IComparable<FT>
        where ST : IComparable<ST>
    { return (p.CompareTo(q) >= 0) ? p : q; }
}
public struct Pair<FT, ST> : IComparable<Pair<FT, ST>>
    where FT : IComparable<FT>
    where ST : IComparable<ST>
{
    public FT x;
    public ST y;
    public Pair(FT f, ST s) : this() { x = f; y = s; }

    public int CompareTo(Pair<FT, ST> other)
    {
        var cmp = x.CompareTo(other.x);
        return cmp != 0 ? cmp : y.CompareTo(other.y);
    }
    public override string ToString() { return string.Format("{0} {1}", x, y); }
}
#endregion

#region ModNumber
public partial struct ModInteger
{
    public static long Mod = (long)1e9 + 7;
    public long num;
    public ModInteger(long n) : this() { num = n % Mod; if (num < 0) num += Mod; }
    public override string ToString() { return num.ToString(); }
    public static ModInteger operator +(ModInteger l, ModInteger r) { var n = l.num + r.num; if (n >= Mod) n -= Mod; return new ModInteger() { num = n }; }
    public static ModInteger operator -(ModInteger l, ModInteger r) { var n = l.num + Mod - r.num; if (n >= Mod) n -= Mod; return new ModInteger() { num = n }; }
    public static ModInteger operator *(ModInteger l, ModInteger r) { return new ModInteger(l.num * r.num); }
    public static ModInteger operator ^(ModInteger l, long r) { return ModInteger.Pow(l, r); }
    public static implicit operator ModInteger(long n) { return new ModInteger(n); }
    public static ModInteger Pow(ModInteger v, long k)
    {
        ModInteger ret = 1;
        var n = k;
        for (; n > 0; n >>= 1, v *= v)
        {
            if ((n & 1) == 1)
                ret = ret * v;
        }
        return ret;
    }
}
#endregion

#region ModMatrix
public class ModMatrix
{
    int row, col;
    public long[] mat;
    public ModInteger this[int r, int c]
    {
        get { return mat[r * col + c]; }
        set { mat[r * col + c] = value.num; }
    }
    public ModMatrix(int r, int c)
    {
        row = r; col = c;
        mat = new long[row * col];
    }
    public static ModMatrix operator +(ModMatrix l, ModMatrix r)
    {
        check(l, r);
        var ret = new ModMatrix(l.row, l.col);
        for (int i = 0; i < l.row; i++)
            for (int j = 0; j < l.col; j++)
            {
                ret.mat[i * ret.col + j] = l.mat[i * l.col + j] + r.mat[i * r.col + j];
                if (ret.mat[i * ret.col + j] >= ModInteger.Mod) ret.mat[i * ret.col + j] -= ModInteger.Mod;
            }
        return ret;

    }
    public static ModMatrix operator *(ModMatrix l, ModMatrix r)
    {
        checkMul(l, r);
        var ret = new ModMatrix(l.row, r.col);
        for (int i = 0; i < l.row; i++)
            for (int k = 0; k < l.col; k++)
                for (int j = 0; j < r.col; j++)
                    ret.mat[i * r.col + j] = (ret.mat[i * r.col + j] + l.mat[i * l.col + k] * r.mat[k * r.col + j]) % ModInteger.Mod;
        return ret;
    }
    public static ModMatrix Pow(ModMatrix m, long n)
    {
        var ret = new ModMatrix(m.row, m.col);
        for (int i = 0; i < m.row; i++)
            ret.mat[i * m.col + i] = 1;
        for (; n > 0; m *= m, n >>= 1)
            if ((n & 1) == 1)
                ret = ret * m;
        return ret;

    }
    public static ModMatrix[] PowTable(ModMatrix m, int k)
    {
        var ret = new ModMatrix[k];
        ret[0] = m;
        for (int i = 1; i < k; i++)
            ret[i] = ret[i - 1] * ret[i - 1];
        return ret;
    }
    public static ModMatrix PowWithTable(ModMatrix m, long n, ModMatrix[] table)
    {
        var ret = new ModMatrix(m.row, m.col);
        for (int i = 0; i < m.row; i++)
            ret.mat[i * m.col + i] = 1;
        for (int i = 0; i < table.Length; i++)
        {
            if ((n & 1) == 1) ret = ret * table[i];
        }
        return ret;
    }
    public static ModMatrix Trans(ModMatrix m)
    {
        var ret = new ModMatrix(m.col, m.row);
        for (int i = 0; i < m.row; i++)
            for (int j = 0; j < m.col; j++)
                ret.mat[j * m.col + i] = m.mat[i * m.col + j];
        return ret;
    }
    [System.Diagnostics.Conditional("DEBUG")]
    static private void check(ModMatrix a, ModMatrix b)
    {
        if (a.row != b.row || a.col != b.col)
            throw new Exception("row and col have to be same.");

    }
    [System.Diagnostics.Conditional("DEBUG")]
    static private void checkMul(ModMatrix a, ModMatrix b)
    {
        if (a.col != b.row)
            throw new Exception("row and col have to be same.");

    }
    public ModInteger[][] Items
    {
        get
        {
            var a = new ModInteger[row][];
            for (int i = 0; i < row; i++)
            {
                a[i] = new ModInteger[col];
                for (int j = 0; j < col; j++)
                    a[i][j] = mat[i * col + j];
            }
            return a;
        }
    }
    public override string ToString()
    {
        return string.Format("{0}*{1}", row, col);
    }
    public void Visualize()
    {
        var items = Items;
        foreach (var x in items)
            System.Diagnostics.Debug.WriteLine(x.AsJoinedString("\t"));
    }
}
#endregion


using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
using Debug = System.Diagnostics.Debug;
using StringBuilder = System.Text.StringBuilder;
using System.Numerics;
using Point = System.Numerics.Complex;
using Number = System.Int64;
namespace Program
{
    public class Solver
    {
        public void Solve()
        {
            var n = sc.Long();
            var k = sc.Long();
            var l = sc.Integer();
            ModInteger.Mod = sc.Long();
            ModInteger ans = 1;
            if (1L << l <= k) ans = 0;
            for (int i = 0; i < l; i++)
            {
                var mat = new ModMatrix(4, 4);
                mat[0, 0] = mat[0, 1] = mat[0, 2] = 1;
                mat[1, 0] = mat[1, 1] = 1;
                mat[2, 3] = 1;
                mat[3, 2] = mat[3, 3] = 1;
                var res = ModMatrix.Pow(mat, n);
                var vec = new ModMatrix(4, 1);
                vec[3, 0] = 1;
                var C = res * vec;
                var mul = C[2, 0] + C[3, 0];
                if ((k >> i & 1) == 1)
                    mul = ModInteger.Pow(2, n) - mul;
                ans *= mul;
                Debug.WriteLine(C[2, 0] + C[3, 0]);

            }
            IO.Printer.Out.WriteLine(ans);
        }
        public IO.StreamScanner sc = new IO.StreamScanner(Console.OpenStandardInput());
        static T[] Enumerate<T>(int n, Func<int, T> f) { var a = new T[n]; for (int i = 0; i < n; ++i) a[i] = f(i); return a; }
        static public void Swap<T>(ref T a, ref T b) { var tmp = a; a = b; b = tmp; }

    }
}
#region main
static class Ex
{
    static public string AsString(this IEnumerable<char> ie) { return new string(System.Linq.Enumerable.ToArray(ie)); }
    static public string AsJoinedString<T>(this IEnumerable<T> ie, string st = " ") { return string.Join(st, ie); }
    static public void Main()
    {
        var solver = new Program.Solver();
        solver.Solve();
        Program.IO.Printer.Out.Flush();
    }
}
#endregion
#region Ex
namespace Program.IO
{
    using System.IO;
    using System.Text;
    using System.Globalization;
    public class Printer : StreamWriter
    {
        static Printer() { Out = new Printer(Console.OpenStandardOutput()) { AutoFlush = false }; }
        public static Printer Out { get; set; }
        public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
        public Printer(System.IO.Stream stream) : base(stream, new UTF8Encoding(false, true)) { }
        public Printer(System.IO.Stream stream, Encoding encoding) : base(stream, encoding) { }
        public void Write<T>(string format, T[] source) { base.Write(format, source.OfType<object>().ToArray()); }
        public void WriteLine<T>(string format, T[] source) { base.WriteLine(format, source.OfType<object>().ToArray()); }
    }
    public class StreamScanner
    {
        public StreamScanner(Stream stream) { str = stream; }
        public readonly Stream str;
        private readonly byte[] buf = new byte[1024];
        private int len, ptr;
        public bool isEof = false;
        public bool IsEndOfStream { get { return isEof; } }
        private byte read()
        {
            if (isEof) return 0;
            if (ptr >= len) { ptr = 0; if ((len = str.Read(buf, 0, 1024)) <= 0) { isEof = true; return 0; } }
            return buf[ptr++];
        }
        public char Char() { byte b = 0; do b = read(); while ((b < 33 || 126 < b) && !isEof); return (char)b; }

        public string Scan()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
                sb.Append(b);
            return sb.ToString();
        }
        public string ScanLine()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b != '\n'; b = (char)read())
                if (b == 0) break;
                else if (b != '\r') sb.Append(b);
            return sb.ToString();
        }
        public long Long()
        {
            if (isEof) return long.MinValue;
            long ret = 0; byte b = 0; var ng = false;
            do b = read();
            while (b != 0 && b != '-' && (b < '0' || '9' < b));
            if (b == 0) return long.MinValue;
            if (b == '-') { ng = true; b = read(); }
            for (; true; b = read())
            {
                if (b < '0' || '9' < b)
                    return ng ? -ret : ret;
                else ret = ret * 10 + b - '0';
            }
        }
        public int Integer() { return (isEof) ? int.MinValue : (int)Long(); }
        public double Double() { var s = Scan(); return s != "" ? double.Parse(s, CultureInfo.InvariantCulture) : double.NaN; }
        private T[] enumerate<T>(int n, Func<T> f)
        {
            var a = new T[n];
            for (int i = 0; i < n; ++i) a[i] = f();
            return a;
        }

        public char[] Char(int n) { return enumerate(n, Char); }
        public string[] Scan(int n) { return enumerate(n, Scan); }
        public double[] Double(int n) { return enumerate(n, Double); }
        public int[] Integer(int n) { return enumerate(n, Integer); }
        public long[] Long(int n) { return enumerate(n, Long); }
    }
}
#endregion
#region Compair
static public class Pair
{
    static public Pair<FT, ST> Create<FT, ST>(FT f, ST s)
        where FT : IComparable<FT>
        where ST : IComparable<ST>
    { return new Pair<FT, ST>(f, s); }
    static public Pair<FT, ST> Min<FT, ST>(Pair<FT, ST> p, Pair<FT, ST> q)
        where FT : IComparable<FT>
        where ST : IComparable<ST>
    { return (p.CompareTo(q) <= 0) ? p : q; }
    static public Pair<FT, ST> Max<FT, ST>(Pair<FT, ST> p, Pair<FT, ST> q)
        where FT : IComparable<FT>
        where ST : IComparable<ST>
    { return (p.CompareTo(q) >= 0) ? p : q; }
}
public struct Pair<FT, ST> : IComparable<Pair<FT, ST>>
    where FT : IComparable<FT>
    where ST : IComparable<ST>
{
    public FT x;
    public ST y;
    public Pair(FT f, ST s) : this() { x = f; y = s; }

    public int CompareTo(Pair<FT, ST> other)
    {
        var cmp = x.CompareTo(other.x);
        return cmp != 0 ? cmp : y.CompareTo(other.y);
    }
    public override string ToString() { return string.Format("{0} {1}", x, y); }
}
#endregion

#region ModNumber
public partial struct ModInteger
{
    public static long Mod = (long)1e9 + 7;
    public long num;
    public ModInteger(long n) : this() { num = n % Mod; if (num < 0) num += Mod; }
    public override string ToString() { return num.ToString(); }
    public static ModInteger operator +(ModInteger l, ModInteger r) { var n = l.num + r.num; if (n >= Mod) n -= Mod; return new ModInteger() { num = n }; }
    public static ModInteger operator -(ModInteger l, ModInteger r) { var n = l.num + Mod - r.num; if (n >= Mod) n -= Mod; return new ModInteger() { num = n }; }
    public static ModInteger operator *(ModInteger l, ModInteger r) { return new ModInteger(l.num * r.num); }
    public static ModInteger operator ^(ModInteger l, long r) { return ModInteger.Pow(l, r); }
    public static implicit operator ModInteger(long n) { return new ModInteger(n); }
    public static ModInteger Pow(ModInteger v, long k)
    {
        ModInteger ret = 1;
        var n = k;
        for (; n > 0; n >>= 1, v *= v)
        {
            if ((n & 1) == 1)
                ret = ret * v;
        }
        return ret;
    }
}
#endregion

#region ModMatrix
public class ModMatrix
{
    int row, col;
    public long[] mat;
    public ModInteger this[int r, int c]
    {
        get { return mat[r * col + c]; }
        set { mat[r * col + c] = value.num; }
    }
    public ModMatrix(int r, int c)
    {
        row = r; col = c;
        mat = new long[row * col];
    }
    public static ModMatrix operator +(ModMatrix l, ModMatrix r)
    {
        check(l, r);
        var ret = new ModMatrix(l.row, l.col);
        for (int i = 0; i < l.row; i++)
            for (int j = 0; j < l.col; j++)
            {
                ret.mat[i * ret.col + j] = l.mat[i * l.col + j] + r.mat[i * r.col + j];
                if (ret.mat[i * ret.col + j] >= ModInteger.Mod) ret.mat[i * ret.col + j] -= ModInteger.Mod;
            }
        return ret;

    }
    public static ModMatrix operator *(ModMatrix l, ModMatrix r)
    {
        checkMul(l, r);
        var ret = new ModMatrix(l.row, r.col);
        for (int i = 0; i < l.row; i++)
            for (int k = 0; k < l.col; k++)
                for (int j = 0; j < r.col; j++)
                    ret.mat[i * r.col + j] = (ret.mat[i * r.col + j] + l.mat[i * l.col + k] * r.mat[k * r.col + j]) % ModInteger.Mod;
        return ret;
    }
    public static ModMatrix Pow(ModMatrix m, long n)
    {
        var ret = new ModMatrix(m.row, m.col);
        for (int i = 0; i < m.row; i++)
            ret.mat[i * m.col + i] = 1;
        for (; n > 0; m *= m, n >>= 1)
            if ((n & 1) == 1)
                ret = ret * m;
        return ret;

    }
    public static ModMatrix[] PowTable(ModMatrix m, int k)
    {
        var ret = new ModMatrix[k];
        ret[0] = m;
        for (int i = 1; i < k; i++)
            ret[i] = ret[i - 1] * ret[i - 1];
        return ret;
    }
    public static ModMatrix PowWithTable(ModMatrix m, long n, ModMatrix[] table)
    {
        var ret = new ModMatrix(m.row, m.col);
        for (int i = 0; i < m.row; i++)
            ret.mat[i * m.col + i] = 1;
        for (int i = 0; i < table.Length; i++)
        {
            if ((n & 1) == 1) ret = ret * table[i];
        }
        return ret;
    }
    public static ModMatrix Trans(ModMatrix m)
    {
        var ret = new ModMatrix(m.col, m.row);
        for (int i = 0; i < m.row; i++)
            for (int j = 0; j < m.col; j++)
                ret.mat[j * m.col + i] = m.mat[i * m.col + j];
        return ret;
    }
    [System.Diagnostics.Conditional("DEBUG")]
    static private void check(ModMatrix a, ModMatrix b)
    {
        if (a.row != b.row || a.col != b.col)
            throw new Exception("row and col have to be same.");

    }
    [System.Diagnostics.Conditional("DEBUG")]
    static private void checkMul(ModMatrix a, ModMatrix b)
    {
        if (a.col != b.row)
            throw new Exception("row and col have to be same.");

    }
    public ModInteger[][] Items
    {
        get
        {
            var a = new ModInteger[row][];
            for (int i = 0; i < row; i++)
            {
                a[i] = new ModInteger[col];
                for (int j = 0; j < col; j++)
                    a[i][j] = mat[i * col + j];
            }
            return a;
        }
    }
    public override string ToString()
    {
        return string.Format("{0}*{1}", row, col);
    }
    public void Visualize()
    {
        var items = Items;
        foreach (var x in items)
            System.Diagnostics.Debug.WriteLine(x.AsJoinedString("\t"));
    }
}
#endregion


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

// (づ°ω°)づﾐ★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    int MOD;

    long[,] MatMult(long[,] a, long[,] b, int n)
    {
        var ret = new long[n, n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                for (int k = 0; k < n; k++)
                    ret[i, j] = (ret[i, j] + a[i, k] * b[k, j]) % MOD;
        return ret;
    }

    long[,] MatPow(long[,] a, int n, long p)
    {
        var ret = new long[n, n];
        for (int i = 0; i < n; i++)
            ret[i, i] = 1;
        while (p > 0)
        {
            if ((p & 1) == 1)
                ret = MatMult(ret, a, n);
            a = MatMult(a, a, n);
            p >>= 1;
        }
        return ret;
    }

    long Fib(long n)
    {
        var a = new long[,] { { 1, 1 }, { 1, 0 } };
        a = MatPow(a, 2, n + 1);
        return a[0, 0];
    }

    int ModPow(long x, long p)
    {
        long ret = 1;
        while (p > 0)
        {
            if ((p & 1) == 1)
                ret = ret * x % MOD;
            x = x * x % MOD;
            p >>= 1;
        }
        return (int)ret;
    }

    void Solve()
    {
        long n = ReadLong();
        long k = ReadLong();
        int l = ReadInt();
        MOD = ReadInt();

        long f = Fib(n);
        long p = (ModPow(2, n) + MOD - f) % MOD;
        long ans = 1;
        for (int i = 0; i < l; i++)
            if ((k >> i & 1) == 1)
                ans = ans * p % MOD;
            else
                ans = ans * f % MOD;

        if ((k >> l) != 0)
            Write(0);
        else
            Write(ans);
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("hull.in");
        //writer = new StreamWriter("hull.out");
#endif
        try
        {
            //            var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //            thread.Start();
            //            thread.Join();
            new Solver().Solve();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
#if DEBUG
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0)currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++)matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++)ret[i][j] = matrix[j][i]; } return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++)lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array)writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++)ret[i] = new T(); return ret; }
    #endregion
}


using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class Program
{
    static int M;

    static void Main(string[] args)
    {
        long[] q1 = Console.ReadLine().Split(' ').Select(t => Int64.Parse(t)).ToArray();
        long N = q1[0];
        long K = q1[1];
        int L = (int)q1[2];
        M = (int)q1[3];

        int[, , ,] dp = new int[65, 2, 2, 2]; // gen, result, head, tail
        dp[0, 0, 0, 0] = 1;
        dp[0, 0, 1, 1] = 1;

        int[,] accum = null;

        for (int i = 1; i <= 64; ++i)
        {
            int[,] prevAccum = null;
            if (((1L << i - 1) & N) != 0)
            {
                if (accum == null)
                {
                    accum = new int[2, 2]; // result, tail
                    accum[0, 0] = (int)(((long)dp[i - 1, 0, 0, 0] + (long)dp[i - 1, 0, 1, 0]) % M);
                    accum[0, 1] = (int)(((long)dp[i - 1, 0, 0, 1] + (long)dp[i - 1, 0, 1, 1]) % M);
                    accum[1, 0] = (int)(((long)dp[i - 1, 1, 0, 0] + (long)dp[i - 1, 1, 1, 0]) % M);
                    accum[1, 1] = (int)(((long)dp[i - 1, 1, 0, 1] + (long)dp[i - 1, 1, 1, 1]) % M);
                }
                else
                {
                    prevAccum = accum;
                    accum = new int[2, 2];
                }
            }

            for (int leftRes = 0; leftRes <= 1; ++leftRes)
            {
                for (int leftTail = 0; leftTail <= 1; ++leftTail)
                {
                    for (int rightRes = 0; rightRes <= 1; ++rightRes)
                    {
                        for (int rightHead = 0; rightHead <= 1; ++rightHead)
                        {
                            for (int rightTail = 0; rightTail <= 1; ++rightTail)
                            {
                                int res = leftRes | rightRes | (leftTail & rightHead);
                                for (int leftHead = 0; leftHead <= 1; ++leftHead)
                                {
                                    long t = (long)dp[i, res, leftHead, rightTail] +
                                        (long)dp[i - 1, leftRes, leftHead, leftTail] * (long)dp[i - 1, rightRes, rightHead, rightTail];

                                    dp[i, res, leftHead, rightTail] = (int)(t % M);
                                }

                                if (prevAccum != null)
                                {
                                    long t = (long)accum[res, rightTail] +
                                        (long)prevAccum[leftRes, leftTail] * (long)dp[i - 1, rightRes, rightHead, rightTail];
                                    accum[res, rightTail] = (int)(t % M);
                                }
                            }
                        }
                    }
                }
            }
        }

        int total = 1;
        for (int i = 0; i < L; ++i)
        {
            if (((1L << i) & K) != 0)
            {
                total = (int)(((long)total * ((long)accum[1, 0] + (long)accum[1, 1])) % M);
            }
            else
            {
                total = (int)(((long)total * ((long)accum[0, 0] + (long)accum[0, 1])) % M);
            }
        }

        for (int i = L; i < 64; ++i)
        {
            if (((1L << i) & K) != 0)
            {
                total = 0;
                break;
            }
        }

        Console.WriteLine(total);
    }
}


#if DEBUG
using System.Reflection;
using System.Threading.Tasks;
#endif

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace _307d
{
	class Program
	{
		static string _inputFilename = "input.txt";
		static string _outputFilename = "output.txt";
#if DEBUG
        static bool _useFileInput = false;
#else
		static bool _useFileInput = false;
#endif

		static void Main(string[] args)
		{
			StreamWriter file = null;
			if (_useFileInput)
			{
				Console.SetIn(File.OpenText(_inputFilename));
				file = new StreamWriter(_outputFilename);
				Console.SetOut(file);
			}

#if DEBUG
			if (!_useFileInput)
			{
				Console.SetIn(getInput());
			}
#endif

			try
			{
				solution();
			}
			finally
			{
				if (_useFileInput)
				{
					file.Close();
				}
			}
		}

		static void solution()
		{
			#region SOLUTION
			var d = readLongArray();
			var n = d[0];
			var k = d[1];
			var l = (int)d[2];
			var m = d[3];

			for (int i = l; i < 64; i++)
			{
				if (((1L << i) & k) != 0)
				{
					Console.WriteLine(0);
					return;
				}
			}

			var fim = new Matrix { _11 = 0, _12 = 1, _21 = 1, _22 = 1 };
			//fim.Print();
			var sq = pow(fim, n - 1, m);
			//sq.Print();

			var fn0 = (sq._21 + sq._22) % m;
			var fn1 = (sq._11 + sq._12) % m;
			var fr = (fn0 + fn1) % m;

			//var fi = new int[n + 1];
			//fi[0] = 1;
			//fi[1] = 1;
			//for (int i = 2; i < n + 1; i++)
			//{
			//	fi[i] = fi[i - 1] + fi[i - 2];
			//}

			var nc = pow(2, n, m);
			nc -= fr;
			if (nc < 0)
			{
				nc += m;
			}
			//nc *= ((n - 1) % m);
			nc %= m;

			var nmod = n % m;
			var res = 1L;
			for (int i = 0; i < l; i++)
			{
				if (((1L << i) & k) != 0)
				{
					res *= nc;
					res %= m;
				}
				else
				{
					res *= fr;
					res %= m;
				}
			}

			Console.WriteLine(res);

			//var n = readInt();
			//var m = readInt();

			//var a = readIntArray();
			//var b = readIntArray();
			#endregion
		}

		class Matrix
		{
			public long _11;
			public long _12;
			public long _21;
			public long _22;

			public void Mult(Matrix x, long mod)
			{
				var __11 = (_11 * x._11) % mod + (_12 * x._21) % mod;
				var __12 = (_11 * x._21) % mod + (_12 * x._22) % mod;
				var __21 = (_21 * x._11) % mod + (_22 * x._21) % mod;
				var __22 = (_21 * x._21) % mod + (_22 * x._22) % mod;

				_11 = __11 % mod;
				_12 = __12 % mod;
				_21 = __21 % mod;
				_22 = __22 % mod;
			}

			public void Square(long mod)
			{
				Mult(this, mod);
			}

			public void Print()
			{
				Console.WriteLine("{0} {1}", _11, _12);
				Console.WriteLine("{0} {1}", _21, _22);
				Console.WriteLine();
			}
		}

		static Matrix pow(Matrix x, long p, long mod)
		{
			//p %= mod;

			var res = new Matrix() { _11 = 1, _22 = 1 };
			var a = new Matrix() { _11 = x._11, _12 = x._12, _21 = x._21, _22 = x._22 };
			while (true)
			{
				if (p % 2 == 1)
				{
					res.Mult(a, mod);
					p--;
				}

				if (p == 0)
				{
					break;
				}

				p /= 2;
				a.Square(mod);
			}

			return res;
		}

		static long pow(long x, long p, long mod)
		{
			x %= mod;
			//p %= mod;

			var res = 1L;
			var a = x;
			while (true)
			{
				if (p % 2 == 1)
				{
					res *= a;
					res %= mod;
					p--;
				}

				if (p == 0)
				{
					break;
				}

				p /= 2;
				a *= a;
				a %= mod;
			}

			return res;
		}

		static int readInt()
		{
			return int.Parse(Console.ReadLine());
		}

		static long readLong()
		{
			return long.Parse(Console.ReadLine());
		}

		static int[] readIntArray()
		{
			return Console.ReadLine().Split(' ').Where(i => !string.IsNullOrEmpty(i)).Select(i => int.Parse(i)).ToArray();
		}

		static long[] readLongArray()
		{
			return Console.ReadLine().Split(' ').Where(i => !string.IsNullOrEmpty(i)).Select(i => long.Parse(i)).ToArray();
		}

#if DEBUG
		static StreamReader getInput()
		{
			var resName = Assembly.GetCallingAssembly().GetManifestResourceNames()[0];
			var resource = Assembly.GetCallingAssembly().GetManifestResourceStream(resName);

			return new StreamReader(resource);
		}
#endif
	}
}


#if DEBUG
using System.Reflection;
using System.Threading.Tasks;
#endif

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace _307d
{
	class Program
	{
		static string _inputFilename = "input.txt";
		static string _outputFilename = "output.txt";
#if DEBUG
        static bool _useFileInput = false;
#else
		static bool _useFileInput = false;
#endif

		static void Main(string[] args)
		{
			StreamWriter file = null;
			if (_useFileInput)
			{
				Console.SetIn(File.OpenText(_inputFilename));
				file = new StreamWriter(_outputFilename);
				Console.SetOut(file);
			}

#if DEBUG
			if (!_useFileInput)
			{
				Console.SetIn(getInput());
			}
#endif

			try
			{
				solution();
			}
			finally
			{
				if (_useFileInput)
				{
					file.Close();
				}
			}
		}

		static void solution()
		{
			#region SOLUTION
			var d = readLongArray();
			var n = d[0];
			var k = d[1];
			var l = (int)d[2];
			var m = d[3];

			for (int i = l; i < 64; i++)
			{
				if (((1L << i) & k) != 0)
				{
					Console.WriteLine(0);
					return;
				}
			}

			var fim = new Matrix { _11 = 0, _12 = 1, _21 = 1, _22 = 1 };
			//fim.Print();
			var sq = pow(fim, n - 1, m);
			//sq.Print();

			var fn0 = (sq._21 + sq._22) % m;
			var fn1 = (sq._11 + sq._12) % m;
			var fr = (fn0 + fn1) % m;

			var nc = pow(2, n, m);
			nc -= fr;
			if (nc < 0)
			{
				nc += m;
			}
			//nc *= ((n - 1) % m);
			nc %= m;

			var nmod = n % m;
			var res = 1L;
			for (int i = 0; i < l; i++)
			{
				if (((1L << i) & k) != 0)
				{
					res *= nc;
					res %= m;
				}
				else
				{
					res *= fr;
					res %= m;
				}
			}

			Console.WriteLine(res);

			//var n = readInt();
			//var m = readInt();

			//var a = readIntArray();
			//var b = readIntArray();
			#endregion
		}

		class Matrix
		{
			public long _11;
			public long _12;
			public long _21;
			public long _22;

			public void Mult(Matrix x, long mod)
			{
				var __11 = (_11 * x._11) % mod + (_12 * x._21) % mod;
				var __12 = (_11 * x._21) % mod + (_12 * x._22) % mod;
				var __21 = (_21 * x._11) % mod + (_22 * x._21) % mod;
				var __22 = (_21 * x._21) % mod + (_22 * x._22) % mod;

				_11 = __11 % mod;
				_12 = __12 % mod;
				_21 = __21 % mod;
				_22 = __22 % mod;
			}

			public void Square(long mod)
			{
				Mult(this, mod);
			}

			public void Print()
			{
				Console.WriteLine("{0} {1}", _11, _12);
				Console.WriteLine("{0} {1}", _21, _22);
				Console.WriteLine();
			}
		}

		static Matrix pow(Matrix x, long p, long mod)
		{
			var res = new Matrix() { _11 = 1, _22 = 1 };
			var a = new Matrix() { _11 = x._11, _12 = x._12, _21 = x._21, _22 = x._22 };
			while (true)
			{
				if (p % 2 == 1)
				{
					res.Mult(a, mod);
					p--;
				}

				if (p == 0)
				{
					break;
				}

				p /= 2;
				a.Square(mod);
			}

			return res;
		}

		static long pow(long x, long p, long mod)
		{
			x %= mod;
			p %= mod;

			var res = 1L;
			var a = x;
			while (true)
			{
				if (p % 2 == 1)
				{
					res *= a;
					res %= mod;
					p--;
				}

				if (p == 0)
				{
					break;
				}

				p /= 2;
				a *= a;
				a %= mod;
			}

			return res;
		}

		static int readInt()
		{
			return int.Parse(Console.ReadLine());
		}

		static long readLong()
		{
			return long.Parse(Console.ReadLine());
		}

		static int[] readIntArray()
		{
			return Console.ReadLine().Split(' ').Where(i => !string.IsNullOrEmpty(i)).Select(i => int.Parse(i)).ToArray();
		}

		static long[] readLongArray()
		{
			return Console.ReadLine().Split(' ').Where(i => !string.IsNullOrEmpty(i)).Select(i => long.Parse(i)).ToArray();
		}

#if DEBUG
		static StreamReader getInput()
		{
			var resName = Assembly.GetCallingAssembly().GetManifestResourceNames()[0];
			var resource = Assembly.GetCallingAssembly().GetManifestResourceStream(resName);

			return new StreamReader(resource);
		}
#endif
	}
}


using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
using Debug = System.Diagnostics.Debug;
using StringBuilder = System.Text.StringBuilder;
using System.Numerics;
using Point = System.Numerics.Complex;
using Number = System.Int64;
namespace Program
{
    public class Solver
    {
        public void Solve()
        {
            var n = sc.Long();
            var k = sc.Long();
            var l = sc.Integer();
            ModInteger.Mod = sc.Long();
            ModInteger ans = 1;
            for (int i = 0; i < l; i++)
            {
                var mat = new ModMatrix(4, 4);
                mat[0, 0] = mat[0, 1] = mat[0, 2] = 1;
                mat[1, 0] = mat[1, 1] = 1;
                mat[2, 3] = 1;
                mat[3, 2] = mat[3, 3] = 1;
                var res = ModMatrix.Pow(mat, n);
                var vec = new ModMatrix(4, 1);
                vec[3, 0] = 1;
                var C = res * vec;
                var to = (int)(k >> i & 1);
                if (to == 1) to = 0;
                else to = 2;
                ans *= C[to, 0] + C[to + 1, 0];
            }
            IO.Printer.Out.WriteLine(ans);
        }
        public IO.StreamScanner sc = new IO.StreamScanner(Console.OpenStandardInput());
        static T[] Enumerate<T>(int n, Func<int, T> f) { var a = new T[n]; for (int i = 0; i < n; ++i) a[i] = f(i); return a; }
        static public void Swap<T>(ref T a, ref T b) { var tmp = a; a = b; b = tmp; }

    }
}
#region main
static class Ex
{
    static public string AsString(this IEnumerable<char> ie) { return new string(System.Linq.Enumerable.ToArray(ie)); }
    static public string AsJoinedString<T>(this IEnumerable<T> ie, string st = " ") { return string.Join(st, ie); }
    static public void Main()
    {
        var solver = new Program.Solver();
        solver.Solve();
        Program.IO.Printer.Out.Flush();
    }
}
#endregion
#region Ex
namespace Program.IO
{
    using System.IO;
    using System.Text;
    using System.Globalization;
    public class Printer : StreamWriter
    {
        static Printer() { Out = new Printer(Console.OpenStandardOutput()) { AutoFlush = false }; }
        public static Printer Out { get; set; }
        public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
        public Printer(System.IO.Stream stream) : base(stream, new UTF8Encoding(false, true)) { }
        public Printer(System.IO.Stream stream, Encoding encoding) : base(stream, encoding) { }
        public void Write<T>(string format, T[] source) { base.Write(format, source.OfType<object>().ToArray()); }
        public void WriteLine<T>(string format, T[] source) { base.WriteLine(format, source.OfType<object>().ToArray()); }
    }
    public class StreamScanner
    {
        public StreamScanner(Stream stream) { str = stream; }
        public readonly Stream str;
        private readonly byte[] buf = new byte[1024];
        private int len, ptr;
        public bool isEof = false;
        public bool IsEndOfStream { get { return isEof; } }
        private byte read()
        {
            if (isEof) return 0;
            if (ptr >= len) { ptr = 0; if ((len = str.Read(buf, 0, 1024)) <= 0) { isEof = true; return 0; } }
            return buf[ptr++];
        }
        public char Char() { byte b = 0; do b = read(); while ((b < 33 || 126 < b) && !isEof); return (char)b; }

        public string Scan()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
                sb.Append(b);
            return sb.ToString();
        }
        public string ScanLine()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b != '\n'; b = (char)read())
                if (b == 0) break;
                else if (b != '\r') sb.Append(b);
            return sb.ToString();
        }
        public long Long()
        {
            if (isEof) return long.MinValue;
            long ret = 0; byte b = 0; var ng = false;
            do b = read();
            while (b != 0 && b != '-' && (b < '0' || '9' < b));
            if (b == 0) return long.MinValue;
            if (b == '-') { ng = true; b = read(); }
            for (; true; b = read())
            {
                if (b < '0' || '9' < b)
                    return ng ? -ret : ret;
                else ret = ret * 10 + b - '0';
            }
        }
        public int Integer() { return (isEof) ? int.MinValue : (int)Long(); }
        public double Double() { var s = Scan(); return s != "" ? double.Parse(s, CultureInfo.InvariantCulture) : double.NaN; }
        private T[] enumerate<T>(int n, Func<T> f)
        {
            var a = new T[n];
            for (int i = 0; i < n; ++i) a[i] = f();
            return a;
        }

        public char[] Char(int n) { return enumerate(n, Char); }
        public string[] Scan(int n) { return enumerate(n, Scan); }
        public double[] Double(int n) { return enumerate(n, Double); }
        public int[] Integer(int n) { return enumerate(n, Integer); }
        public long[] Long(int n) { return enumerate(n, Long); }
    }
}
#endregion
#region Compair
static public class Pair
{
    static public Pair<FT, ST> Create<FT, ST>(FT f, ST s)
        where FT : IComparable<FT>
        where ST : IComparable<ST>
    { return new Pair<FT, ST>(f, s); }
    static public Pair<FT, ST> Min<FT, ST>(Pair<FT, ST> p, Pair<FT, ST> q)
        where FT : IComparable<FT>
        where ST : IComparable<ST>
    { return (p.CompareTo(q) <= 0) ? p : q; }
    static public Pair<FT, ST> Max<FT, ST>(Pair<FT, ST> p, Pair<FT, ST> q)
        where FT : IComparable<FT>
        where ST : IComparable<ST>
    { return (p.CompareTo(q) >= 0) ? p : q; }
}
public struct Pair<FT, ST> : IComparable<Pair<FT, ST>>
    where FT : IComparable<FT>
    where ST : IComparable<ST>
{
    public FT x;
    public ST y;
    public Pair(FT f, ST s) : this() { x = f; y = s; }

    public int CompareTo(Pair<FT, ST> other)
    {
        var cmp = x.CompareTo(other.x);
        return cmp != 0 ? cmp : y.CompareTo(other.y);
    }
    public override string ToString() { return string.Format("{0} {1}", x, y); }
}
#endregion

#region ModNumber
public partial struct ModInteger
{
    public static long Mod = (long)1e9 + 7;
    public long num;
    public ModInteger(long n) : this() { num = n % Mod; if (num < 0) num += Mod; }
    public override string ToString() { return num.ToString(); }
    public static ModInteger operator +(ModInteger l, ModInteger r) { var n = l.num + r.num; if (n >= Mod) n -= Mod; return new ModInteger() { num = n }; }
    public static ModInteger operator -(ModInteger l, ModInteger r) { var n = l.num + Mod - r.num; if (n >= Mod) n -= Mod; return new ModInteger() { num = n }; }
    public static ModInteger operator *(ModInteger l, ModInteger r) { return new ModInteger(l.num * r.num); }
    public static ModInteger operator ^(ModInteger l, long r) { return ModInteger.Pow(l, r); }
    public static implicit operator ModInteger(long n) { return new ModInteger(n); }
    public static ModInteger Pow(ModInteger v, long k)
    {
        ModInteger ret = 1;
        var n = k;
        for (; n > 0; n >>= 1, v *= v)
        {
            if ((n & 1) == 1)
                ret = ret * v;
        }
        return ret;
    }
}
#endregion

#region ModMatrix
public class ModMatrix
{
    int row, col;
    public long[] mat;
    public ModInteger this[int r, int c]
    {
        get { return mat[r * col + c]; }
        set { mat[r * col + c] = value.num; }
    }
    public ModMatrix(int r, int c)
    {
        row = r; col = c;
        mat = new long[row * col];
    }
    public static ModMatrix operator +(ModMatrix l, ModMatrix r)
    {
        check(l, r);
        var ret = new ModMatrix(l.row, l.col);
        for (int i = 0; i < l.row; i++)
            for (int j = 0; j < l.col; j++)
            {
                ret.mat[i * ret.col + j] = l.mat[i * l.col + j] + r.mat[i * r.col + j];
                if (ret.mat[i * ret.col + j] >= ModInteger.Mod) ret.mat[i * ret.col + j] -= ModInteger.Mod;
            }
        return ret;

    }
    public static ModMatrix operator *(ModMatrix l, ModMatrix r)
    {
        checkMul(l, r);
        var ret = new ModMatrix(l.row, r.col);
        for (int i = 0; i < l.row; i++)
            for (int k = 0; k < l.col; k++)
                for (int j = 0; j < r.col; j++)
                    ret.mat[i * r.col + j] = (ret.mat[i * r.col + j] + l.mat[i * l.col + k] * r.mat[k * r.col + j]) % ModInteger.Mod;
        return ret;
    }
    public static ModMatrix Pow(ModMatrix m, long n)
    {
        var ret = new ModMatrix(m.row, m.col);
        for (int i = 0; i < m.row; i++)
            ret.mat[i * m.col + i] = 1;
        for (; n > 0; m *= m, n >>= 1)
            if ((n & 1) == 1)
                ret = ret * m;
        return ret;

    }
    public static ModMatrix[] PowTable(ModMatrix m, int k)
    {
        var ret = new ModMatrix[k];
        ret[0] = m;
        for (int i = 1; i < k; i++)
            ret[i] = ret[i - 1] * ret[i - 1];
        return ret;
    }
    public static ModMatrix PowWithTable(ModMatrix m, long n, ModMatrix[] table)
    {
        var ret = new ModMatrix(m.row, m.col);
        for (int i = 0; i < m.row; i++)
            ret.mat[i * m.col + i] = 1;
        for (int i = 0; i < table.Length; i++)
        {
            if ((n & 1) == 1) ret = ret * table[i];
        }
        return ret;
    }
    public static ModMatrix Trans(ModMatrix m)
    {
        var ret = new ModMatrix(m.col, m.row);
        for (int i = 0; i < m.row; i++)
            for (int j = 0; j < m.col; j++)
                ret.mat[j * m.col + i] = m.mat[i * m.col + j];
        return ret;
    }
    [System.Diagnostics.Conditional("DEBUG")]
    static private void check(ModMatrix a, ModMatrix b)
    {
        if (a.row != b.row || a.col != b.col)
            throw new Exception("row and col have to be same.");

    }
    [System.Diagnostics.Conditional("DEBUG")]
    static private void checkMul(ModMatrix a, ModMatrix b)
    {
        if (a.col != b.row)
            throw new Exception("row and col have to be same.");

    }
    public ModInteger[][] Items
    {
        get
        {
            var a = new ModInteger[row][];
            for (int i = 0; i < row; i++)
            {
                a[i] = new ModInteger[col];
                for (int j = 0; j < col; j++)
                    a[i][j] = mat[i * col + j];
            }
            return a;
        }
    }
    public override string ToString()
    {
        return string.Format("{0}*{1}", row, col);
    }
    public void Visualize()
    {
        var items = Items;
        foreach (var x in items)
            System.Diagnostics.Debug.WriteLine(x.AsJoinedString("\t"));
    }
}
#endregion


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

// (づ°ω°)づﾐ★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    int MOD;

    long[,] MatMult(long[,] a, long[,] b, int n)
    {
        var ret = new long[n, n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                for (int k = 0; k < n; k++)
                    ret[i, j] = (ret[i, j] + a[i, k] * b[k, j]) % MOD;
        return ret;
    }

    long[,] MatPow(long[,] a, int n, long p)
    {
        var ret = new long[n, n];
        for (int i = 0; i < n; i++)
            ret[i, i] = 1;
        while (p > 0)
        {
            if ((p & 1) == 1)
                ret = MatMult(ret, a, n);
            a = MatMult(a, a, n);
            p >>= 1;
        }
        return ret;
    }

    long Fib(long n)
    {
        var a = new long[,] { { 1, 1 }, { 1, 0 } };
        a = MatPow(a, 2, n + 1);
        return a[0, 0];
    }

    int ModPow(long x, long p)
    {
        long ret = 1;
        while (p > 0)
        {
            if ((p & 1) == 1)
                ret = ret * x % MOD;
            x = x * x % MOD;
            p >>= 1;
        }
        return (int)ret;
    }

    void Solve()
    {
        long n = ReadLong();
        long k = ReadLong();
        int l = ReadInt();
        MOD = ReadInt();

        long f = Fib(n);
        long p = (ModPow(2, n) + MOD - f) % MOD;
        long ans = 1;
        for (int i = 0; i < l; i++)
            if ((k >> i & 1) == 1)
                ans = ans * p % MOD;
            else
                ans = ans * f % MOD;

        if (l < 60 && (k >> l) != 0)
            Write(0);
        else
            Write(ans);
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("hull.in");
        //writer = new StreamWriter("hull.out");
#endif
        try
        {
            //            var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //            thread.Start();
            //            thread.Join();
            new Solver().Solve();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
#if DEBUG
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0)currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++)matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++)ret[i][j] = matrix[j][i]; } return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++)lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array)writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++)ret[i] = new T(); return ret; }
    #endregion
}


using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class Program
{
    static int M;

    static void Main(string[] args)
    {
        long[] q1 = Console.ReadLine().Split(' ').Select(t => Int64.Parse(t)).ToArray();
        long N = q1[0];
        long K = q1[1];
        int L = (int)q1[2];
        M = (int)q1[3];

        int[, , ,] dp = new int[65, 2, 2, 2]; // gen, result, head, tail
        dp[0, 0, 0, 0] = 1;
        dp[0, 0, 1, 1] = 1;

        int[,] accum = null;

        for (int i = 1; i <= 64; ++i)
        {
            int[,] prevAccum = null;
            if (((1L << i - 1) & N) != 0)
            {
                if (accum == null)
                {
                    accum = new int[2, 2]; // result, tail
                    accum[0, 0] = (int)(((long)dp[i - 1, 0, 0, 0] + (long)dp[i - 1, 0, 1, 0]) % M);
                    accum[0, 1] = (int)(((long)dp[i - 1, 0, 0, 1] + (long)dp[i - 1, 0, 1, 1]) % M);
                    accum[1, 0] = (int)(((long)dp[i - 1, 1, 0, 0] + (long)dp[i - 1, 1, 1, 0]) % M);
                    accum[1, 1] = (int)(((long)dp[i - 1, 1, 0, 1] + (long)dp[i - 1, 1, 1, 1]) % M);
                }
                else
                {
                    prevAccum = accum;
                    accum = new int[2, 2];
                }
            }

            for (int leftRes = 0; leftRes <= 1; ++leftRes)
            {
                for (int leftTail = 0; leftTail <= 1; ++leftTail)
                {
                    for (int rightRes = 0; rightRes <= 1; ++rightRes)
                    {
                        for (int rightHead = 0; rightHead <= 1; ++rightHead)
                        {
                            for (int rightTail = 0; rightTail <= 1; ++rightTail)
                            {
                                int res = leftRes | rightRes | (leftTail & rightHead);
                                for (int leftHead = 0; leftHead <= 1; ++leftHead)
                                {
                                    long t = (long)dp[i, res, leftHead, rightTail] +
                                        (long)dp[i - 1, leftRes, leftHead, leftTail] * (long)dp[i - 1, rightRes, rightHead, rightTail];

                                    dp[i, res, leftHead, rightTail] = (int)(t % M);
                                }

                                if (prevAccum != null)
                                {
                                    long t = (long)accum[res, rightTail] +
                                        (long)prevAccum[leftRes, leftTail] * (long)dp[i - 1, rightRes, rightHead, rightTail];
                                    accum[res, rightTail] = (int)(t % M);
                                }
                            }
                        }
                    }
                }
            }
        }

        int total = 1 % M;
        for (int i = 0; i < L; ++i)
        {
            if (((1L << i) & K) != 0)
            {
                total = (int)(((long)total * ((long)accum[1, 0] + (long)accum[1, 1])) % M);
            }
            else
            {
                total = (int)(((long)total * ((long)accum[0, 0] + (long)accum[0, 1])) % M);
            }
        }

        for (int i = L; i < 64; ++i)
        {
            if (((1L << i) & K) != 0)
            {
                total = 0;
                break;
            }
        }

        Console.WriteLine(total);
    }
}


using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
using Debug = System.Diagnostics.Debug;
using StringBuilder = System.Text.StringBuilder;
using System.Numerics;
using Point = System.Numerics.Complex;
using Number = System.Int64;
namespace Program
{
    public class Solver
    {
        public void Solve()
        {
            var n = sc.Long();
            var k = sc.Long();
            var l = sc.Integer();
            ModInteger.Mod = sc.Long();
            ModInteger ans = 1;
            if ((1L << Math.Min(62, l)) <= k)
                ans = 0;
            for (int i = 0; i < l; i++)
            {
                var mat = new ModMatrix(4, 4);
                mat[0, 0] = mat[0, 1] = mat[0, 2] = 1;
                mat[1, 0] = mat[1, 1] = 1;
                mat[2, 3] = 1;
                mat[3, 2] = mat[3, 3] = 1;
                var res = ModMatrix.Pow(mat, n);
                var vec = new ModMatrix(4, 1);
                vec[3, 0] = 1;
                var C = res * vec;
                var mul = C[2, 0] + C[3, 0];
                if ((k >> i & 1) == 1)
                    mul = ModInteger.Pow(2, n) - mul;
                ans *= mul;
                Debug.WriteLine(C[2, 0] + C[3, 0]);

            }
            IO.Printer.Out.WriteLine(ans);
        }
        public IO.StreamScanner sc = new IO.StreamScanner(Console.OpenStandardInput());
        static T[] Enumerate<T>(int n, Func<int, T> f) { var a = new T[n]; for (int i = 0; i < n; ++i) a[i] = f(i); return a; }
        static public void Swap<T>(ref T a, ref T b) { var tmp = a; a = b; b = tmp; }

    }
}
#region main
static class Ex
{
    static public string AsString(this IEnumerable<char> ie) { return new string(System.Linq.Enumerable.ToArray(ie)); }
    static public string AsJoinedString<T>(this IEnumerable<T> ie, string st = " ") { return string.Join(st, ie); }
    static public void Main()
    {
        var solver = new Program.Solver();
        solver.Solve();
        Program.IO.Printer.Out.Flush();
    }
}
#endregion
#region Ex
namespace Program.IO
{
    using System.IO;
    using System.Text;
    using System.Globalization;
    public class Printer : StreamWriter
    {
        static Printer() { Out = new Printer(Console.OpenStandardOutput()) { AutoFlush = false }; }
        public static Printer Out { get; set; }
        public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
        public Printer(System.IO.Stream stream) : base(stream, new UTF8Encoding(false, true)) { }
        public Printer(System.IO.Stream stream, Encoding encoding) : base(stream, encoding) { }
        public void Write<T>(string format, T[] source) { base.Write(format, source.OfType<object>().ToArray()); }
        public void WriteLine<T>(string format, T[] source) { base.WriteLine(format, source.OfType<object>().ToArray()); }
    }
    public class StreamScanner
    {
        public StreamScanner(Stream stream) { str = stream; }
        public readonly Stream str;
        private readonly byte[] buf = new byte[1024];
        private int len, ptr;
        public bool isEof = false;
        public bool IsEndOfStream { get { return isEof; } }
        private byte read()
        {
            if (isEof) return 0;
            if (ptr >= len) { ptr = 0; if ((len = str.Read(buf, 0, 1024)) <= 0) { isEof = true; return 0; } }
            return buf[ptr++];
        }
        public char Char() { byte b = 0; do b = read(); while ((b < 33 || 126 < b) && !isEof); return (char)b; }

        public string Scan()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
                sb.Append(b);
            return sb.ToString();
        }
        public string ScanLine()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b != '\n'; b = (char)read())
                if (b == 0) break;
                else if (b != '\r') sb.Append(b);
            return sb.ToString();
        }
        public long Long()
        {
            if (isEof) return long.MinValue;
            long ret = 0; byte b = 0; var ng = false;
            do b = read();
            while (b != 0 && b != '-' && (b < '0' || '9' < b));
            if (b == 0) return long.MinValue;
            if (b == '-') { ng = true; b = read(); }
            for (; true; b = read())
            {
                if (b < '0' || '9' < b)
                    return ng ? -ret : ret;
                else ret = ret * 10 + b - '0';
            }
        }
        public int Integer() { return (isEof) ? int.MinValue : (int)Long(); }
        public double Double() { var s = Scan(); return s != "" ? double.Parse(s, CultureInfo.InvariantCulture) : double.NaN; }
        private T[] enumerate<T>(int n, Func<T> f)
        {
            var a = new T[n];
            for (int i = 0; i < n; ++i) a[i] = f();
            return a;
        }

        public char[] Char(int n) { return enumerate(n, Char); }
        public string[] Scan(int n) { return enumerate(n, Scan); }
        public double[] Double(int n) { return enumerate(n, Double); }
        public int[] Integer(int n) { return enumerate(n, Integer); }
        public long[] Long(int n) { return enumerate(n, Long); }
    }
}
#endregion
#region Compair
static public class Pair
{
    static public Pair<FT, ST> Create<FT, ST>(FT f, ST s)
        where FT : IComparable<FT>
        where ST : IComparable<ST>
    { return new Pair<FT, ST>(f, s); }
    static public Pair<FT, ST> Min<FT, ST>(Pair<FT, ST> p, Pair<FT, ST> q)
        where FT : IComparable<FT>
        where ST : IComparable<ST>
    { return (p.CompareTo(q) <= 0) ? p : q; }
    static public Pair<FT, ST> Max<FT, ST>(Pair<FT, ST> p, Pair<FT, ST> q)
        where FT : IComparable<FT>
        where ST : IComparable<ST>
    { return (p.CompareTo(q) >= 0) ? p : q; }
}
public struct Pair<FT, ST> : IComparable<Pair<FT, ST>>
    where FT : IComparable<FT>
    where ST : IComparable<ST>
{
    public FT x;
    public ST y;
    public Pair(FT f, ST s) : this() { x = f; y = s; }

    public int CompareTo(Pair<FT, ST> other)
    {
        var cmp = x.CompareTo(other.x);
        return cmp != 0 ? cmp : y.CompareTo(other.y);
    }
    public override string ToString() { return string.Format("{0} {1}", x, y); }
}
#endregion

#region ModNumber
public partial struct ModInteger
{
    public static long Mod = (long)1e9 + 7;
    public long num;
    public ModInteger(long n) : this() { num = n % Mod; if (num < 0) num += Mod; }
    public override string ToString() { return num.ToString(); }
    public static ModInteger operator +(ModInteger l, ModInteger r) { var n = l.num + r.num; if (n >= Mod) n -= Mod; return new ModInteger() { num = n }; }
    public static ModInteger operator -(ModInteger l, ModInteger r) { var n = l.num + Mod - r.num; if (n >= Mod) n -= Mod; return new ModInteger() { num = n }; }
    public static ModInteger operator *(ModInteger l, ModInteger r) { return new ModInteger(l.num * r.num); }
    public static ModInteger operator ^(ModInteger l, long r) { return ModInteger.Pow(l, r); }
    public static implicit operator ModInteger(long n) { return new ModInteger(n); }
    public static ModInteger Pow(ModInteger v, long k)
    {
        ModInteger ret = 1;
        var n = k;
        for (; n > 0; n >>= 1, v *= v)
        {
            if ((n & 1) == 1)
                ret = ret * v;
        }
        return ret;
    }
}
#endregion

#region ModMatrix
public class ModMatrix
{
    int row, col;
    public long[] mat;
    public ModInteger this[int r, int c]
    {
        get { return mat[r * col + c]; }
        set { mat[r * col + c] = value.num; }
    }
    public ModMatrix(int r, int c)
    {
        row = r; col = c;
        mat = new long[row * col];
    }
    public static ModMatrix operator +(ModMatrix l, ModMatrix r)
    {
        check(l, r);
        var ret = new ModMatrix(l.row, l.col);
        for (int i = 0; i < l.row; i++)
            for (int j = 0; j < l.col; j++)
            {
                ret.mat[i * ret.col + j] = l.mat[i * l.col + j] + r.mat[i * r.col + j];
                if (ret.mat[i * ret.col + j] >= ModInteger.Mod) ret.mat[i * ret.col + j] -= ModInteger.Mod;
            }
        return ret;

    }
    public static ModMatrix operator *(ModMatrix l, ModMatrix r)
    {
        checkMul(l, r);
        var ret = new ModMatrix(l.row, r.col);
        for (int i = 0; i < l.row; i++)
            for (int k = 0; k < l.col; k++)
                for (int j = 0; j < r.col; j++)
                    ret.mat[i * r.col + j] = (ret.mat[i * r.col + j] + l.mat[i * l.col + k] * r.mat[k * r.col + j]) % ModInteger.Mod;
        return ret;
    }
    public static ModMatrix Pow(ModMatrix m, long n)
    {
        var ret = new ModMatrix(m.row, m.col);
        for (int i = 0; i < m.row; i++)
            ret.mat[i * m.col + i] = 1;
        for (; n > 0; m *= m, n >>= 1)
            if ((n & 1) == 1)
                ret = ret * m;
        return ret;

    }
    public static ModMatrix[] PowTable(ModMatrix m, int k)
    {
        var ret = new ModMatrix[k];
        ret[0] = m;
        for (int i = 1; i < k; i++)
            ret[i] = ret[i - 1] * ret[i - 1];
        return ret;
    }
    public static ModMatrix PowWithTable(ModMatrix m, long n, ModMatrix[] table)
    {
        var ret = new ModMatrix(m.row, m.col);
        for (int i = 0; i < m.row; i++)
            ret.mat[i * m.col + i] = 1;
        for (int i = 0; i < table.Length; i++)
        {
            if ((n & 1) == 1) ret = ret * table[i];
        }
        return ret;
    }
    public static ModMatrix Trans(ModMatrix m)
    {
        var ret = new ModMatrix(m.col, m.row);
        for (int i = 0; i < m.row; i++)
            for (int j = 0; j < m.col; j++)
                ret.mat[j * m.col + i] = m.mat[i * m.col + j];
        return ret;
    }
    [System.Diagnostics.Conditional("DEBUG")]
    static private void check(ModMatrix a, ModMatrix b)
    {
        if (a.row != b.row || a.col != b.col)
            throw new Exception("row and col have to be same.");

    }
    [System.Diagnostics.Conditional("DEBUG")]
    static private void checkMul(ModMatrix a, ModMatrix b)
    {
        if (a.col != b.row)
            throw new Exception("row and col have to be same.");

    }
    public ModInteger[][] Items
    {
        get
        {
            var a = new ModInteger[row][];
            for (int i = 0; i < row; i++)
            {
                a[i] = new ModInteger[col];
                for (int j = 0; j < col; j++)
                    a[i][j] = mat[i * col + j];
            }
            return a;
        }
    }
    public override string ToString()
    {
        return string.Format("{0}*{1}", row, col);
    }
    public void Visualize()
    {
        var items = Items;
        foreach (var x in items)
            System.Diagnostics.Debug.WriteLine(x.AsJoinedString("\t"));
    }
}
#endregion


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

// (づ°ω°)づﾐ★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    int MOD;

    long[,] MatMult(long[,] a, long[,] b, int n)
    {
        var ret = new long[n, n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                for (int k = 0; k < n; k++)
                    ret[i, j] = (ret[i, j] + a[i, k] * b[k, j]) % MOD;
        return ret;
    }

    long[,] MatPow(long[,] a, int n, long p)
    {
        var ret = new long[n, n];
        for (int i = 0; i < n; i++)
            ret[i, i] = 1;
        while (p > 0)
        {
            if ((p & 1) == 1)
                ret = MatMult(ret, a, n);
            a = MatMult(a, a, n);
            p >>= 1;
        }
        return ret;
    }

    long Fib(long n)
    {
        var a = new long[,] { { 1, 1 }, { 1, 0 } };
        a = MatPow(a, 2, n + 1);
        return a[0, 0];
    }

    int ModPow(long x, long p)
    {
        long ret = 1;
        while (p > 0)
        {
            if ((p & 1) == 1)
                ret = ret * x % MOD;
            x = x * x % MOD;
            p >>= 1;
        }
        return (int)ret;
    }

    void Solve()
    {
        long n = ReadLong();
        long k = ReadLong();
        int l = ReadInt();
        MOD = ReadInt();

        long f = Fib(n);
        long p = (ModPow(2, n) + MOD - f) % MOD;
        long ans = 1;
        for (int i = 0; i < l; i++)
            if ((k >> i & 1) == 1)
                ans = ans * p % MOD;
            else
                ans = ans * f % MOD;

        if (l < 60 && (k >> l) != 0)
            Write(0);
        else
            Write(ans % MOD);
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("hull.in");
        //writer = new StreamWriter("hull.out");
#endif
        try
        {
            //            var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //            thread.Start();
            //            thread.Join();
            new Solver().Solve();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
#if DEBUG
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0)currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++)matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++)ret[i][j] = matrix[j][i]; } return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++)lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array)writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++)ret[i] = new T(); return ret; }
    #endregion
}


#if DEBUG
using System.Reflection;
using System.Threading.Tasks;
#endif

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace _307d
{
	class Program
	{
		static string _inputFilename = "input.txt";
		static string _outputFilename = "output.txt";
#if DEBUG
        static bool _useFileInput = false;
#else
		static bool _useFileInput = false;
#endif

		static void Main(string[] args)
		{
			StreamWriter file = null;
			if (_useFileInput)
			{
				Console.SetIn(File.OpenText(_inputFilename));
				file = new StreamWriter(_outputFilename);
				Console.SetOut(file);
			}

#if DEBUG
			if (!_useFileInput)
			{
				Console.SetIn(getInput());
			}
#endif

			try
			{
				solution();
			}
			finally
			{
				if (_useFileInput)
				{
					file.Close();
				}
			}
		}

		static void solution()
		{
			#region SOLUTION
			var d = readLongArray();
			var n = d[0];
			var k = d[1];
			var l = (int)d[2];
			var m = d[3];

			//if (l == 0)
			//{
			//	Console.WriteLine(0);
			//	return;
			//}

			for (int i = l; i < 64; i++)
			{
				if (((1L << i) & k) != 0)
				{
					Console.WriteLine(0);
					return;
				}
			}

			var fim = new Matrix { _11 = 0, _12 = 1, _21 = 1, _22 = 1 };
			//fim.Print();
			var sq = pow(fim, n - 1, m);
			//sq.Print();

			var fn0 = (sq._21 + sq._22) % m;
			var fn1 = (sq._11 + sq._12) % m;
			var fr = (fn0 + fn1) % m;

			//var fi = new int[n + 1];
			//fi[0] = 1;
			//fi[1] = 1;
			//for (int i = 2; i < n + 1; i++)
			//{
			//	fi[i] = fi[i - 1] + fi[i - 2];
			//}

			var nc = pow(2, n, m);
			nc -= fr;
			if (nc < 0)
			{
				nc += m;
			}
			//nc *= ((n - 1) % m);
			nc %= m;

			var res = 1L;
			for (int i = 0; i < l; i++)
			{
				if (((1L << i) & k) != 0)
				{
					res *= nc;
					res %= m;
				}
				else
				{
					res *= fr;
					res %= m;
				}
			}

			Console.WriteLine(res % m);

			//var n = readInt();
			//var m = readInt();

			//var a = readIntArray();
			//var b = readIntArray();
			#endregion
		}

		class Matrix
		{
			public long _11;
			public long _12;
			public long _21;
			public long _22;

			public void Mult(Matrix x, long mod)
			{
				var __11 = (_11 * x._11) % mod + (_12 * x._21) % mod;
				var __12 = (_11 * x._21) % mod + (_12 * x._22) % mod;
				var __21 = (_21 * x._11) % mod + (_22 * x._21) % mod;
				var __22 = (_21 * x._21) % mod + (_22 * x._22) % mod;

				_11 = __11 % mod;
				_12 = __12 % mod;
				_21 = __21 % mod;
				_22 = __22 % mod;
			}

			public void Square(long mod)
			{
				Mult(this, mod);
			}

			public void Print()
			{
				Console.WriteLine("{0} {1}", _11, _12);
				Console.WriteLine("{0} {1}", _21, _22);
				Console.WriteLine();
			}
		}

		static Matrix pow(Matrix x, long p, long mod)
		{
			//p %= mod;

			var res = new Matrix() { _11 = 1, _22 = 1 };
			var a = new Matrix() { _11 = x._11, _12 = x._12, _21 = x._21, _22 = x._22 };
			while (true)
			{
				if (p % 2 == 1)
				{
					res.Mult(a, mod);
					p--;
				}

				if (p == 0)
				{
					break;
				}

				p /= 2;
				a.Square(mod);
			}

			return res;
		}

		static long pow(long x, long p, long mod)
		{
			x %= mod;
			//p %= mod;

			var res = 1L;
			var a = x;
			while (true)
			{
				if (p % 2 == 1)
				{
					res *= a;
					res %= mod;
					p--;
				}

				if (p == 0)
				{
					break;
				}

				p /= 2;
				a *= a;
				a %= mod;
			}

			return res;
		}

		static int readInt()
		{
			return int.Parse(Console.ReadLine());
		}

		static long readLong()
		{
			return long.Parse(Console.ReadLine());
		}

		static int[] readIntArray()
		{
			return Console.ReadLine().Split(' ').Where(i => !string.IsNullOrEmpty(i)).Select(i => int.Parse(i)).ToArray();
		}

		static long[] readLongArray()
		{
			return Console.ReadLine().Split(' ').Where(i => !string.IsNullOrEmpty(i)).Select(i => long.Parse(i)).ToArray();
		}

#if DEBUG
		static StreamReader getInput()
		{
			var resName = Assembly.GetCallingAssembly().GetManifestResourceNames()[0];
			var resource = Assembly.GetCallingAssembly().GetManifestResourceStream(resName);

			return new StreamReader(resource);
		}
#endif
	}
}


#if DEBUG
using System.Reflection;
using System.Threading.Tasks;
#endif

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace _307d
{
	class Program
	{
		static string _inputFilename = "input.txt";
		static string _outputFilename = "output.txt";
#if DEBUG
        static bool _useFileInput = false;
#else
		static bool _useFileInput = false;
#endif

		static void Main(string[] args)
		{
			StreamWriter file = null;
			if (_useFileInput)
			{
				Console.SetIn(File.OpenText(_inputFilename));
				file = new StreamWriter(_outputFilename);
				Console.SetOut(file);
			}

#if DEBUG
			if (!_useFileInput)
			{
				Console.SetIn(getInput());
			}
#endif

			try
			{
				solution();
			}
			finally
			{
				if (_useFileInput)
				{
					file.Close();
				}
			}
		}

		static void solution()
		{
			#region SOLUTION
			var d = readLongArray();
			var n = d[0];
			var k = d[1];
			var l = (int)d[2];
			var m = d[3];

			for (int i = l; i < 64; i++)
			{
				if (((1L << i) & k) != 0)
				{
					Console.WriteLine(0);
					return;
				}
			}

			var fim = new Matrix { _11 = 0, _12 = 1, _21 = 1, _22 = 1 };
			//fim.Print();
			var sq = pow(fim, n - 1, m);
			//sq.Print();

			var fn0 = (sq._21 + sq._22) % m;
			var fn1 = (sq._11 + sq._12) % m;
			var fr = (fn0 + fn1) % m;

			var fi = new int[n + 1];
			fi[0] = 1;
			fi[1] = 1;
			for (int i = 2; i < n + 1; i++)
			{
				fi[i] = fi[i - 1] + fi[i - 2];
			}

			var nc = pow(2, n, m);
			nc -= fr;
			if (nc < 0)
			{
				nc += m;
			}
			//nc *= ((n - 1) % m);
			nc %= m;

			var nmod = n % m;
			var res = 1L;
			for (int i = 0; i < l; i++)
			{
				if (((1L << i) & k) != 0)
				{
					res *= nc;
					res %= m;
				}
				else
				{
					res *= fr;
					res %= m;
				}
			}

			Console.WriteLine(res);

			//var n = readInt();
			//var m = readInt();

			//var a = readIntArray();
			//var b = readIntArray();
			#endregion
		}

		class Matrix
		{
			public long _11;
			public long _12;
			public long _21;
			public long _22;

			public void Mult(Matrix x, long mod)
			{
				var __11 = (_11 * x._11) % mod + (_12 * x._21) % mod;
				var __12 = (_11 * x._21) % mod + (_12 * x._22) % mod;
				var __21 = (_21 * x._11) % mod + (_22 * x._21) % mod;
				var __22 = (_21 * x._21) % mod + (_22 * x._22) % mod;

				_11 = __11 % mod;
				_12 = __12 % mod;
				_21 = __21 % mod;
				_22 = __22 % mod;
			}

			public void Square(long mod)
			{
				Mult(this, mod);
			}

			public void Print()
			{
				Console.WriteLine("{0} {1}", _11, _12);
				Console.WriteLine("{0} {1}", _21, _22);
				Console.WriteLine();
			}
		}

		static Matrix pow(Matrix x, long p, long mod)
		{
			//p %= mod;

			var res = new Matrix() { _11 = 1, _22 = 1 };
			var a = new Matrix() { _11 = x._11, _12 = x._12, _21 = x._21, _22 = x._22 };
			while (true)
			{
				if (p % 2 == 1)
				{
					res.Mult(a, mod);
					p--;
				}

				if (p == 0)
				{
					break;
				}

				p /= 2;
				a.Square(mod);
			}

			return res;
		}

		static long pow(long x, long p, long mod)
		{
			x %= mod;
			//p %= mod;

			var res = 1L;
			var a = x;
			while (true)
			{
				if (p % 2 == 1)
				{
					res *= a;
					res %= mod;
					p--;
				}

				if (p == 0)
				{
					break;
				}

				p /= 2;
				a *= a;
				a %= mod;
			}

			return res;
		}

		static int readInt()
		{
			return int.Parse(Console.ReadLine());
		}

		static long readLong()
		{
			return long.Parse(Console.ReadLine());
		}

		static int[] readIntArray()
		{
			return Console.ReadLine().Split(' ').Where(i => !string.IsNullOrEmpty(i)).Select(i => int.Parse(i)).ToArray();
		}

		static long[] readLongArray()
		{
			return Console.ReadLine().Split(' ').Where(i => !string.IsNullOrEmpty(i)).Select(i => long.Parse(i)).ToArray();
		}

#if DEBUG
		static StreamReader getInput()
		{
			var resName = Assembly.GetCallingAssembly().GetManifestResourceNames()[0];
			var resource = Assembly.GetCallingAssembly().GetManifestResourceStream(resName);

			return new StreamReader(resource);
		}
#endif
	}
}


using System;

public class Program
{
	public static void Main()
	{
		string[] input = Console.ReadLine().Split(' ');
		double a1 = double.Parse(input[0]);
		double b1 = double.Parse(input[1]);
		double c1 = double.Parse(input[2]);

		input = Console.ReadLine().Split(' ');
		double a2 = double.Parse(input[0]);
		double b2 = double.Parse(input[1]);
		double c2 = double.Parse(input[2]);

		if((a1 == 0 && b1 == 0 && c1 == 0) || (a2 == 0 && b2 == 0 && c2 == 0))
		{
			Console.WriteLine(-1);
		}
		if(b1 == 0 && b2 == 0 && c1 == c2)
		{
			Console.WriteLine(-1);
		}
		else if(b1 == 0 && b2 == 0 && c1 != c2)
		{
			Console.WriteLine(0);
		}
		else if(a1 / b1 == a2 / b2 && c1 == c2)
		{
			Console.WriteLine(-1);
		}
		else if(a1 / b1 == a2 / b2 && c1 != c2)
		{
			Console.WriteLine(0);
		}
		else
		{
			Console.WriteLine(1);
		}
	}
}


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

namespace CodeForces
{
    static class Reader
    {
        public static int NextInt()
        {
            int ret = 0;
            char c;

            while (!char.IsDigit(c = (char)Console.Read()))
            {
                if (c == '-')
                    return -NextInt();
            }
            do
            {
                ret = ret * 10 + c - '0';
            } while (char.IsDigit(c = (char)Console.Read()));

            return ret;
        }

        public static double NextDouble()
        {
            double ret = 0;
            char c;

            while (!char.IsDigit(c = (char)Console.Read()))
            {
                if (c == '-')
                    return -NextDouble();
            }
            do
            {
                ret = ret * 10 + c - '0';
            } while (char.IsDigit(c = (char)Console.Read()));
            if (c != '.') return ret;

            double p10 = 0.1;
            while (char.IsDigit(c = (char)Console.Read()))
            {
                ret += p10 * (c - '0');
                p10 *= 0.1;
            }

            return ret;
        }

        public static string NextToken()
        {
            StringBuilder ret = new StringBuilder();
            char c;

            while (char.IsWhiteSpace(c = (char)Console.Read())) ;
            do
            {
                ret.Append(c);
            } while (!char.IsWhiteSpace(c = (char)Console.Read()));

            return ret.ToString();
        }
    }

    class Program
    {
        static int GCD(int n, int m)
        {
            return m > 0 ? GCD(m, n % m) : n;
        }

        static void Get(out int A, out int B, out int C)
        {
            int a = Reader.NextInt();
            int b = Reader.NextInt();
            int c = Reader.NextInt();

            int g = GCD(Math.Abs(a), GCD(Math.Abs(b), Math.Abs(c)));
            if (g == 0)
                g = 1;

            A = a / g;
            B = b / g;
            C = c / g;
        }

        static void Main(string[] args)
        {
            int A1, B1, C1, A2, B2, C2;

            Get(out A1, out B1, out C1);
            Get(out A2, out B2, out C2);

            bool inf = (A1 == 0 && B1 == 0 && C1 == 0) || (A2 == 0 && B2 == 0 && C2 == 0);
            bool no = (A1 == 0 && B1 == 0 && C1 != 0) || (A2 == 0 && B2 == 0 && C2 != 0);

            if ((A1 == A2 && B1 == B2 && C1 == C2) || (inf && !no))
            {
                Console.WriteLine(-1);
                return;
            }

            if (A1 * B2 == A2 * B1 || no)
            {
                Console.WriteLine(0);
                return;
            }

            Console.WriteLine(1);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Numerics;

// (づ°ω°)づﾐe★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    int Gcd(int a, int b)
    {
        return b > 0 ? Gcd(b, a % b) : a;
    }

    public void Solve()
    {
        var a = ReadIntMatrix(2);

        if (a[0][0] == 0 && a[0][1] == 0)
        {
            if (a[0][2] != 0 || a[1][0] == 0 && a[1][1] == 0 && a[1][2] != 0)
                Write(0);
            else
                Write(-1);
            return;
        }

        if (a[1][0] == 0 && a[1][1] == 0)
        {
            Write(a[1][2] == 0 ? -1 : 0);
            return;
        }

        for (int i = 0; i < 2; i++)
        {
            int g = 0;
            for (int j = 0; j < 3; j++)
                g = Gcd(g, Math.Abs(a[i][j]));
            for (int j = 0; j < 3; j++)
                a[i][j] /= g;

            if (a[i][0] < 0 || a[i][0] == 0 && a[i][1] < 0)
                for (int j = 0; j < 3; j++)
                    a[i][j] = -a[i][j];
        }

        if (a[0][0] == 0 && a[1][0] == 0)
            Write(a[0][1] == a[1][1] && a[0][2] == a[1][2] ? -1 : 0);
        else if (a[0][1] == 0 && a[1][1] == 0)
            Write(a[0][0] == a[1][0] && a[0][2] == a[1][2] ? -1 : 0);
        else if (a[0][0] == a[1][0] && a[0][1] == a[1][1])
            Write(a[0][2] == a[1][2] ? -1 : 0);
        else
            Write(1);
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("input.txt");
        //writer = new StreamWriter("output.txt");
#endif
        try
        {
            new Solver().Solve();
            //var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //thread.Start();
            //thread.Join();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
#if DEBUG
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0)currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++)matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++)ret[i][j] = matrix[j][i]; } return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++)lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array)writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++)ret[i] = new T(); return ret; }
    #endregion
}


using System;

public class Program
{
	public static void Main()
	{
		string[] input = Console.ReadLine().Split(' ');
		double a1 = double.Parse(input[0]);
		double b1 = double.Parse(input[1]);
		double c1 = double.Parse(input[2]);

		input = Console.ReadLine().Split(' ');
		double a2 = double.Parse(input[0]);
		double b2 = double.Parse(input[1]);
		double c2 = double.Parse(input[2]);

		if((a1 == 0 && b1 == 0 && c1 == 0) || (a2 == 0 && b2 == 0 && c2 == 0))
		{
			Console.WriteLine(-1);
		}
		else if(b1 == 0 && b2 == 0 && c1 == c2)
		{
			Console.WriteLine(-1);
		}
		else if(b1 == 0 && b2 == 0 && c1 != c2)
		{
			Console.WriteLine(0);
		}
		else if(a1 / b1 == a2 / b2 && c1 == c2)
		{
			Console.WriteLine(-1);
		}
		else if(a1 / b1 == a2 / b2 && c1 != c2)
		{
			Console.WriteLine(0);
		}
		else
		{
			Console.WriteLine(1);
		}
	}
}


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

namespace CodeForces
{
    static class Reader
    {
        public static int NextInt()
        {
            int ret = 0;
            char c;

            while (!char.IsDigit(c = (char)Console.Read()))
            {
                if (c == '-')
                    return -NextInt();
            }
            do
            {
                ret = ret * 10 + c - '0';
            } while (char.IsDigit(c = (char)Console.Read()));

            return ret;
        }

        public static double NextDouble()
        {
            double ret = 0;
            char c;

            while (!char.IsDigit(c = (char)Console.Read()))
            {
                if (c == '-')
                    return -NextDouble();
            }
            do
            {
                ret = ret * 10 + c - '0';
            } while (char.IsDigit(c = (char)Console.Read()));
            if (c != '.') return ret;

            double p10 = 0.1;
            while (char.IsDigit(c = (char)Console.Read()))
            {
                ret += p10 * (c - '0');
                p10 *= 0.1;
            }

            return ret;
        }

        public static string NextToken()
        {
            StringBuilder ret = new StringBuilder();
            char c;

            while (char.IsWhiteSpace(c = (char)Console.Read())) ;
            do
            {
                ret.Append(c);
            } while (!char.IsWhiteSpace(c = (char)Console.Read()));

            return ret.ToString();
        }
    }

    class Program
    {
        static int GCD(int n, int m)
        {
            return m > 0 ? GCD(m, n % m) : n;
        }

        static void Get(out int A, out int B, out int C)
        {
            int a = Reader.NextInt();
            int b = Reader.NextInt();
            int c = Reader.NextInt();

            int g = GCD(Math.Abs(a), GCD(Math.Abs(b), Math.Abs(c)));
            if (g == 0)
                g = 1;

            A = a / g;
            B = b / g;
            C = c / g;

            if (A <= 0 && B <= 0 && C <= 0)
            {
                A = -A;
                B = -B;
                C = -C;
            }
        }

        static void Main(string[] args)
        {
            int A1, B1, C1, A2, B2, C2;

            Get(out A1, out B1, out C1);
            Get(out A2, out B2, out C2);

            bool inf = (A1 == 0 && B1 == 0 && C1 == 0) || (A2 == 0 && B2 == 0 && C2 == 0);
            bool no = (A1 == 0 && B1 == 0 && C1 != 0) || (A2 == 0 && B2 == 0 && C2 != 0);

            if (!no && ((A1 == A2 && B1 == B2 && C1 == C2) || inf))
            {
                Console.WriteLine(-1);
                return;
            }

            if (A1 * B2 == A2 * B1 || no)
            {
                Console.WriteLine(0);
                return;
            }

            Console.WriteLine(1);
        }
    }
}


using System;

public class Program
{
	public static void Main()
	{
		string[] input = Console.ReadLine().Split(' ');
		double a1 = double.Parse(input[0]);
		double b1 = double.Parse(input[1]);
		double c1 = double.Parse(input[2]);

		input = Console.ReadLine().Split(' ');
		double a2 = double.Parse(input[0]);
		double b2 = double.Parse(input[1]);
		double c2 = double.Parse(input[2]);

		if(b1 == 0 && b2 == 0 && c1 == c2)
		{
			Console.WriteLine(-1);
		}
		else if(b1 == 0 && b2 == 0 && c1 != c2)
		{
			Console.WriteLine(0);
		}
		else if(a1 / b1 == a2 / b2 && c1 == c2)
		{
			Console.WriteLine(-1);
		}
		else if(a1 / b1 == a2 / b2 && c1 != c2)
		{
			Console.WriteLine(0);
		}
		else
		{
			Console.WriteLine(1);
		}
	}
}