您的位置:首页 > 运维架构

CF551D:GukiZ and Binary Operations(矩阵 & 思维)

2017-08-07 23:09 453 查看
D. GukiZ and Binary Operations

time limit per test
1 second

memory limit per test
256 megabytes

input
standard input

output
standard output

We all know that GukiZ often plays with arrays.

Now he is thinking about this problem: how many arrays a, of length n,
with non-negative elements strictly less then 2l meet
the following condition: 

?
Here operation 

 means
bitwise AND (in Pascal it is equivalent to and, in C/C++/Java/Python it
is equivalent to &), operation 

 means
bitwise OR (in Pascal it is equivalent to 

,
in C/C++/Java/Python it is equivalent to |).

Because the answer can be quite large, calculate it modulo m. This time GukiZ hasn't come up with solution, and needs you to help him!

Input

First and the only line of input contains four integers n, k, l, m (2 ≤ n ≤ 1018, 0 ≤ k ≤ 1018, 0 ≤ l ≤ 64, 1 ≤ m ≤ 109 + 7).

Output

In the single line print the number of arrays satisfying the condition above modulo m.

Examples

input
2 1 2 10


output
3


input
2 1 1 3


output
1


input
3 3 2 10


output
9


Note

In the first sample, satisfying arrays are {1, 1}, {3, 1}, {1, 3}.

In the second sample, only satisfying array is {1, 1}.

In the third sample, satisfying arrays are {0, 3, 3}, {1, 3, 2}, {1, 3, 3}, {2, 3, 1}, {2, 3, 3}, {3, 3, 0}, {3, 3, 1}, {3, 3, 2}, {3, 3, 3}.

题意:问有几个N元组满足每个值<2^l,且...=k。

思路:观察K的二进制,若某一位为0,即任意两个相邻数该位不同时为1,若某一位为1,至少有一对相邻数该位同时为1,那么不同时为1用dp算的话就是斐波拉契数列,范围太大用矩阵快速幂,然后注意l为64或63时不能用long long判断0。

# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
LL n, k, l, mod, num, num2;
struct Mat{LL mat[2][2];};
LL qmod(LL a, LL b)
{
LL ans = 1;
for(;b;b>>=1)
{
if(b&1) ans = ans*a%mod;
a = a*a%mod;
}
return ans;
}
Mat operator *(Mat a, Mat b)//矩阵相乘。
{
Mat c;
for(int i=0; i<2; ++i)
for(int j=0; j<2; ++j)
{
c.mat[i][j] = 0;
for(int k=0; k<2; ++k)
c.mat[i][j] = (c.mat[i][j] + a.mat[i][k]*b.mat[k][j]%mod)%mod;
}
return c;
}
Mat operator ^(Mat a, LL k)
{
Mat c;
for(int i=0; i<2; ++i)
for(int j=0; j<2; ++j)
c.mat[i][j] = (i==j);
for(;k;k>>=1)
{
if(k&1) c = c*a;
a = a*a;
}
return c;
}
LL solve()
{
LL ans = 1;
for(LL i=0; i<l; ++i)
{
int bit = (k&(1LL<<i))?1:0;
if(!bit) ans = ans*num%mod;
else ans = ans*((num2-num+mod)%mod)%mod;
}
return ans%mod;
}
int main()
{
scanf("%lld%lld%lld%lld",&n,&k,&l,&mod);
if(l!=64 && k >= (1ULL<<l)) return 0*puts("0");
Mat a;
a.mat[0][0] = a.mat[1][0] = a.mat[0][1] = 1LL;
a.mat[1][1] = 0;
a = a^n;
num = (a.mat[0][0]+a.mat[0][1])%mod;
num2 = qmod(2,n);
printf("%lld\n",solve());
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: