热情好客的请森林中的朋友们吃饭,他的朋友被编号为 1~N,每个到来的朋友都会带给他一些礼物:。其中,第一个朋友会带给他 1 个,之后,每一个朋友到来以后,都会带给他之前所有人带来的礼物个数再加他的编号的 K 次方那么多个。所以,假设 K=2,前几位朋友带来的礼物个数分别是:1,5,15,37,83假设 K=3,前几位朋友带来的礼物个数分别是:1,9,37,111现在,好奇自己到底能收到第 N 个朋友多少礼物,因此拜托于你了。已知 N,K请输出第 N 个朋友送的礼物个数 mod1000000007。
一个整数,表示第 N 个朋友送的礼物个数 mod1000000007。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const ll P=1000000007;
ll n;
ll c[20][20];
int m;
struct M
{
ll a[20][20];
M () {memset(a,0,sizeof(a));}
ll * operator [] (int b){return a[b];}
M operator * (M b)
{
M c;
int i,j,k;
for(i=0;i<=m+1;i++) for(j=0;j<=m+1;j++) for(k=0;k<=m+1;k++) c[i][j]=(c[i][j]+a[i][k]*b[k][j])%P;
return c;
}
}tr,a1,a2;
M pm(M ret,ll y)
{
M x=tr;
while(y)
{
if(y&1) ret=ret*x;
x=x*x,y>>=1;
}
return ret;
}
int main()
{
scanf("%lld%d",&n,&m);
int i,j;
c[0][0]=1;
for(i=1;i<=m;i++)
{
c[i][0]=1;
for(j=1;j<=i;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j])%P;
}
for(i=0;i<=m;i++)
{
a1[0][i]=a2[0][i]=1;
for(j=0;j<=i;j++) tr[j][i]=c[i][j];
}
tr[m+1][m+1]=2,tr[m][m+1]=1;
a1=pm(a1,n-1),a2=pm(a2,n);
printf("%lld",(a2[0][m+1]-a1[0][m+1]+P)%P);
return 0;
}