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!
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).
In the single line print the number of arrays satisfying the condition above modulo m.
2 1 2 10
3
2 1 1 3
1
3 3 2 10
9
解题思路:
我们把K分解成2进制的形式,对K的每一个二进制位进行处理,当L大于K的长度的时候我们分两种情况处理,一种是L-count_bit(K)中,每一位的方案数均为长度为N的0,1序列中,不存在连续1的方案数,存在连续1的方案数为总的方案数减去连续1的方案数,对count_bit(K)的计算我们跟据K所在位是0还是1乘以相应的方案数,注意对一些例如K=0,count_bit(K) > L等情况的一些特判。
不存在连续1的方案数的计算方法是采用递推的方法:f(n) = f(n-1) + f(n-2), 思路一会儿就想出来了,但是这题得注意整数的溢出问题,我们需要将本题中所有参与的运算全部改成64位整型,我就是被这一点坑了好久,实在是蛋疼啊,这次算是长记性了,坑爹啊,该收拾东西回宿舍了。
#include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <string> #include <vector> #include <deque> #include <queue> #include <stack> #include <map> #include <set> #include <utility> #include <algorithm> #include <functional> using namespace std; typedef long long ll; ll N, K, L, M; struct Matrix { ll mat[2][2]; void clear() { memset(mat, 0, sizeof(mat)); } void init() { memset(mat, 0, sizeof(mat)); mat[0][0] = mat[1][1] = 1; } friend Matrix operator + (const Matrix &a, const Matrix &b) { Matrix c; c.clear(); for(int i = 0; i < 2; ++i) { for(int j = 0; j < 2; ++j) { c.mat[i][j] = (a.mat[i][j] + b.mat[i][j]) % M; } } return c; } friend Matrix operator * (const Matrix &a, const Matrix &b) { Matrix c; c.clear(); for(int i = 0; i < 2; ++i) { for(int j = 0; j < 2; ++j) { for(int k = 0; k < 2; ++k) { c.mat[i][j] = (c.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % M; } } } return c; } friend Matrix operator ^ (Matrix a, ll x) { Matrix ret; ret.init(); while(x) { if(x & 1) ret = ret * a; a = a * a; x >>= 1; } return ret; } }; int count_bit(ll x) { int bit = 0; if(x == 0) return 1; while(x) { bit++; x >>= 1; } return bit; } ll mul_mod(ll a, ll b) { ll ret = 0; while(b) { if(b & 1) ret = (ret + a) % M; a = a * 2 % M; b >>= 1; } return ret; } ll power_mod(ll a, ll b) { ll ret = 1; while(b) { if(b&1) ret = mul_mod(ret, a); a = mul_mod(a, a); b >>= 1; } return ret; } int main() { //freopen("aa.in", "r", stdin); scanf("%I64d %I64d %I64d %I64d", &N, &K, &L, &M); if(L == 0 && K == 0) { printf("%I64d\n", 1LL%M); } else if(count_bit(K) > L) { printf("0\n"); } else { Matrix a; a.mat[0][0] = 0; a.mat[0][1] = 1; a.mat[1][0] = 1; a.mat[1][1] = 1; a = a^(N-1); ll t1 = (1*a.mat[0][1] + 2*a.mat[1][1]) % M; ll t2 = ((power_mod(2LL, N) - t1) % M + M) % M; ll x1 = L - count_bit(K); ll x2 = count_bit(K); ll y1, y2 = 1; y1 = power_mod(t1, x1); for(int i = 0; i < x2; ++i) { if(K&(1LL<<i)) { // 注意 1<<i 可能溢出, 应该改为 1LL << i y2 = mul_mod(y2, t2); } else { y2 = mul_mod(y2, t1); } } printf("%I64d\n", mul_mod(y1, y2)); } return 0; }