D. GukiZ and Binary Operations
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard 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}.
这个题其实思路是这样的
把那个k二进制分开
因为每一位之间互相不影响所以只要一位一位的判断就可以了
还要注意的一个东西是取余…
不知道怎么回事取到了负的??
不过无所谓…
以后取余数一定要注意最后变成正的
然后因为是一位一位的判断
一位是1的条件其实只要连续两个是1就可以的
然后求的时候就是有点技巧
一开始可以看做是一个dp
二维的 求得是这意味是0的情况
这个dp第一维是求第几位第二维是求这个是1还是0
打个表转移就可以
发现其实是个斐波那契
然后理所当然的矩阵快速幂
处理一些特殊情况就可以
比如l的位数其实比k多?、
比如l其实比k小?
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
long long n, k, m, l;
struct juzhen
{
long long zz[2][2];
};
juzhen cheng(juzhen p, juzhen q)
{
juzhen qq = { { { 0,0 },{ 0,0 } } };
for (int a = 0;a < 2;a++)
{
for (int b = 0;b < 2;b++)
{
for (int c = 0;c < 2;c++)
{
qq.zz[a][b] += (p.zz[a][c] * q.zz[c][b]) % m;
}
}
}
return qq;
}
juzhen ksm(juzhen di, long long zhishu)
{
juzhen fanhui;
for (int a = 0;a < 2;a++)
{
for (int b = 0;b < 2;b++)
{
if (a == b)fanhui.zz[a][b] = 1;
else fanhui.zz[a][b] = 0;
}
}
while (zhishu)
{
if (zhishu & 1)fanhui = cheng(fanhui, di);
zhishu >>= 1;
di = cheng(di, di);
}
return fanhui;
}
long long kksm(long long di, long long zhishu)
{
long long fanhui = 1;
while (zhishu)
{
if (zhishu & 1)fanhui *= di;
fanhui %= m;
zhishu >>= 1;
di *= di;
di %= m;
}
return fanhui%m;
}
int main()
{
cin >> n >> k >> l >> m;
if (pow(2,l) <= k)
{
cout << 0;
return 0;
}
juzhen kp;
kp.zz[0][0] = kp.zz[0][1] = kp.zz[1][0] = 1;
kp.zz[1][1] = 0;
long long ling, yi;
kp = ksm(kp, n);
ling = (kp.zz[0][0] + kp.zz[0][1]) % m;
long long quan = kksm(2, n);
yi = quan - ling;
long long jg = 1;
while (k)
{
if (k & 1)jg *= yi;
else jg *= ling;
k >>= 1;
jg %= m;
l--;
}
while (l >= 1)
{
jg *= ling;
jg %= m;
l--;
}
jg += m;
jg %= m;
cout << jg;
return 0;
}