求斐波那契数列的第n项 :https://www.cnblogs.com/guozhenqiang/p/5489081.html
#include<stdio.h>
#include<string.h>
#define N 4
long long m;
long long tmp[N][N],res[N][N];
long long w[4][4];
void multi(long long a[][N],long long b[][N],int n)//a矩阵和b矩阵相乘
{
memset(tmp,0,sizeof tmp);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
for(int k=0;k<n;k++)
{
if(a[i][k]*b[k][j]>m)
tmp[i][j]+=a[i][k]*b[k][j]%m;
else
tmp[i][j]+=a[i][k]*b[k][j];
if(tmp[i][j]>m)
tmp[i][j]%=m;
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
a[i][j]=tmp[i][j];
}
}
void Pow(long long a[][N],long long n)//矩阵的n次方
{
memset(res,0,sizeof res);
for(int i=0;i<N;i++)
res[i][i]=1;
while(n)
{
//printf("\n");
if(n&1)
multi(res,a,N);
multi(a,a,N);
n>>=1;
}
}
int a[70];//k的二进制形式
long long cal(long long a,long long b,long long mod)//a的b次方
{
long long sum=1;
a=a%mod;
while(b>0)
{
if(b%2==1)
sum=(sum*a)%mod;
b/=2;
a=(a*a)%mod;
}
return sum;
}
int main()
{
w[0][0]=1;
w[0][1]=1;
w[1][0]=1;
w[1][1]=0;
long long n,k,l,answer,x/*0*/,y/*1*/,z/*2^n*/,num1=0,num0=0;
scanf("%lld%lld%lld%lld",&n,&k,&l,&m);
long long k1=k;
int cnt=0;
while(k1>0)
{
a[cnt++]=k1%2;
k1/=2;
}
/*for(int i=0;i<cnt;i++)
printf("%d",a[i]);
printf("\n");*/
if(cnt>l)
{
printf("0\n");
return 0;
}
Pow(w,n+1);
x=res[0][0];/*0*/
//printf("res:\n%d %d\n",res[0][0],res[0][1]);
//printf("%d %d\n",res[1][0],res[1][1]);
z=cal(2,n,m);/*2^n*/
if(z>x)
y=z-x;
else
y=z+m-x;/*1*/
//printf("x=%lld y=%lld z=%lld\n",x,y,z);
for(int i=0;i<cnt;i++)
if(a[i]==1)
num1++;
num0=cnt-num1;
//printf("num0=%lld num1=%lld\n",num0,num1);
answer=cal(x,num0,m)*cal(y,num1,m);
answer=answer%m;
//printf("%lld\n",answer);
answer=answer*cal(x,l-cnt,m);
answer=answer%m;
printf("%lld\n",answer);
return 0;
}