数组长度为n,, l是数位长度,m是取模数
满足的 每一个a都小于2^l 的数组数目是多少?
按某一位来看,如果k的某一位是1,那么必须满足至少相邻两个a的某一位都是1,
如果k的那位是0,则数组相邻的a那一位不全是1.
可以证得 k是0时,数组a的种类数随着长度的增加满足斐波那契数列。
于是题目可以变成计算F(n)的值,和2^n-F(n) 分别是k的某位为0和1的情况
由于N为1e18,需矩阵快速幂。
l为63时longlong会变负,64会溢出
PS : 模为1的时候答案一定为0!
#include<bits/stdc++.h>
#define For(i,a,b) for(int (i)=(a);(i) < (b);(i)++)
#define rof(i,a,b) for(int (i)=(a);(i) > (b);(i)--)
#define IOS ios::sync_with_stdio(false)
#define lson l,m,rt <<1
#define rson m+1,r,rt<<1|1
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int maxn = 2e5+10;
const int INF =0x3f3f3f3f;
int MOD;
ll n,k,l;
struct MATRIC{
ll ele[5][5];
MATRIC(){mem(ele,0);}
};
MATRIC mul ( ll n, MATRIC m1, MATRIC m2)
{
MATRIC ans;
For(i,0,n){
For(j,0,n){
ll ret=0;
For(k,0,n){
ret=(ret+m1.ele[i][k]*m2.ele[k][j]%MOD)%MOD;
}
ans.ele[i][j]=ret;
}
}
return ans;
}
MATRIC matric_mul_pow(MATRIC m1,ll b)
{
MATRIC ans;
For(i,0,2)
For(j,0,2)
if(i==j)ans.ele[i][j]=1;
while(b){
if(b&1){
ans=mul(2,ans,m1);
}
b>>=1;
m1=mul(2,m1,m1);
}
return ans;
}
ll pow2(ll b)
{
ll ans=1,a=2;
while(b){
if(b&1) ans=(ans*a)%MOD;
b>>=1;
a=a*a%MOD;
}
return ans;
}
int main()
{
cin>>n>>k>>l>>MOD;
MATRIC m;
ll y=1;
if(l<63){
y<<=l;
if(y<=k) {
cout<<0<<endl;
return 0;
}
}
m.ele[0][0]=0;m.ele[0][1]=1;m.ele[1][0]=1;m.ele[1][1]=1;
m=matric_mul_pow(m,n);
ll x=(m.ele[0][1]+m.ele[1][1])%MOD;
y=(pow2(n)-x+MOD)%MOD;
ll ans=1;
for(int i=0;i<l;i++){
if(i==63){
ans=(ans*x)%MOD;
break;
}
if(k&1) ans=(ans*y)%MOD;
else ans=(ans*x)%MOD;
k>>=1;
}
//cout<<x<<endl<<y<<endl;
cout<<ans%MOD<<endl;
return 0;
}