矩阵快速幂
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef __int64 LL;
const int mod=1e9+7;
const int N=100;
int K;
void pri(LL A[N][N]){
for(int i=0;i<K;i++){
for(int j=0;j<K;j++){
printf("%I64d ",A[i][j]);
}printf("\n");
}printf("\n");
}
void cp(LL A[N][N],LL C[N][N]){
for(int i=0;i<K;i++){
for(int j=0;j<K;j++){
A[i][j]=C[i][j];
}
}
}
LL C[N][N];
void mul(LL A[N][N],LL B[N][N]){
memset(C,0,sizeof(C));
for(int i=0;i<K;i++){
for(int j=0;j<K;j++){
for(int k=0;k<K;k++){
C[i][j]+=A[i][k]*B[k][j]%mod;
C[i][j]%=mod;
}
}
}
cp(A,C);
}
LL D[N][N];
void mpow(LL A[N][N],LL b){
//pri(A);
memset(D,0,sizeof(D));
for(int i=0;i<K;i++){
D[i][i]=1;
}
while(b){
//printf("%I64d\n",b);
if(b&1){
mul(D,A);
}
mul(A,A);b/=2;
}
cp(A,D);
}
LL A[N][N];
LL B[N][N];
LL c[N][N];
LL FC(int i,int j){
if(i<j)return 0;
return c[i][j];
}
int main(){
#ifdef DouBi
freopen("in.cpp","r",stdin);
#endif // DouBi
LL n;
int k;
n=40;
c[0][0]=1;
for(int i=1;i<=n;i++){
c[i][0]=c[i][i]=1;
for(int j=1;j<i;j++){
c[i][j]=c[i-1][j]+c[i-1][j-1];
c[i][j]%=mod;
}
}
while(scanf("%I64d%d",&n,&k)!=EOF){
memset(A,0,sizeof(A));
for(int i=0;i<=k;i++){
for(int j=0;j<=i;j++){
A[1+i][1+j]=FC(i,j);
A[1+i][1+k+1+j]=FC(i,j);
}
}
for(int i=0;i<=k;i++){
for(int j=0;j<=i;j++){
A[1+k+1+i][1+j]=FC(i,j);
}
}
A[0][0]=1;
for(int i=0;i<=k;i++){
A[0][1+i]=FC(k,i);
A[0][1+k+1+i]=FC(k,i);
}
K=1+k+1+k+1;
//pri(A);
mpow(A,n-1);
//pri(A);
memset(B,0,sizeof(B));
for(int i=0;i<K;i++){
B[i][0]=1;
}
//pri(B);
mul(A,B);
printf("%I64d\n",A[0][0]);
}
return 0;
}