传送门
令
F
i
F_i
Fi为前
i
i
i项的和。那么有:
F
i
=
2
∗
F
i
−
1
+
i
k
F_i=2*F_{i-1}+i^k
Fi=2∗Fi−1+ik
我们考虑如何让后面可以用矩阵转移!
由于有二项式定理:
i
k
=
∑
t
=
0
k
(
k
t
)
(
i
−
1
)
t
i^k=\sum_{t=0}^{k} \binom{k}{t}(i-1)^t
ik=t=0∑k(tk)(i−1)t
那么可以把原式写成:
F
i
=
2
∗
F
i
−
1
+
(
k
0
)
(
i
−
1
)
0
+
(
k
1
)
(
i
−
1
)
1
+
⋯
+
(
k
k
)
(
i
−
1
)
k
F_i=2*F_{i-1}+\binom{k}{0}(i-1)^0+\binom{k}{1}(i-1)^1+\cdots+\binom{k}{k}(i-1)^k
Fi=2∗Fi−1+(0k)(i−1)0+(1k)(i−1)1+⋯+(kk)(i−1)k
于是可以构造出
[
2
(
k
0
)
(
k
1
)
(
k
2
)
⋯
(
k
k
)
0
(
0
0
)
0
0
0
0
0
(
1
0
)
(
1
1
)
0
⋯
0
⋮
⋮
⋮
⋮
⋮
⋮
0
(
k
0
)
(
k
1
)
(
k
2
)
⋯
(
k
k
)
]
[
F
i
−
1
(
i
−
1
)
0
(
i
−
1
)
1
⋮
(
i
−
1
)
k
]
=
[
F
i
i
0
i
1
⋮
i
k
]
\left[ \begin{matrix} 2 & \binom{k}{0} & \binom{k}{1} & \binom{k}{2} & \cdots & \binom{k}{k}\\ \\ 0 & \binom{0}{0} & 0 & 0 & 0 & 0 \\ \\ 0 & \binom{1}{0} & \binom{1}{1} & 0 & \cdots &0\\ \\ \vdots & \vdots & \vdots & \vdots & \vdots& \vdots\\ \\ 0 & \binom{k}{0} & \binom{k}{1} & \binom{k}{2} & \cdots &\binom{k}{k}\\ \end{matrix} \right] \left[ \begin{matrix} F_{i-1} \\ (i-1)^0\\ (i-1)^1\\ \vdots\\ (i-1)^k\\ \end{matrix} \right]= \left[ \begin{matrix} F_i \\ i^0 \\ i^1 \\ \vdots \\ i^k \\ \end{matrix} \right]
⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡200⋮0(0k)(00)(01)⋮(0k)(1k)0(11)⋮(1k)(2k)00⋮(2k)⋯0⋯⋮⋯(kk)00⋮(kk)⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤⎣⎢⎢⎢⎢⎢⎡Fi−1(i−1)0(i−1)1⋮(i−1)k⎦⎥⎥⎥⎥⎥⎤=⎣⎢⎢⎢⎢⎢⎡Fii0i1⋮ik⎦⎥⎥⎥⎥⎥⎤
这些系数也是根据二项式定理得出的,于是这题就没了。注意
n
n
n读进来是
l
o
n
g
l
o
n
g
long\ long
long long。矩阵快速幂算出来的是前
n
n
n项的和,于是我们算出前
n
−
1
n-1
n−1项的和(只用乘
n
−
2
n-2
n−2次)再加上当前位置的贡献即可。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7,N=12;
int k,fac[N],ifac[N];ll n;
inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline int quickpow(int a,int b,int ret=1){for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
inline void Add(int &x,int y){x=(x+y>=mod)?x+y-mod:x+y;}
inline int C(int n,int m){return n<m?0:mul(fac[n],mul(ifac[m],ifac[n-m]));}
struct matrix{
int a[N][N];
matrix(int t=0){
memset(a,0,sizeof(a));
for(int i=0;i<N;++i) a[i][i]=t;
}
inline void init(int k){
a[0][0]=2;
for(int j=1;j<=k+1;++j) a[0][j]=C(k,j-1);
for(int i=1;i<=k+1;++i)
for(int j=1;j<=i;++j)
a[i][j]=C(i-1,j-1);
}
inline int getval(int ret=0){
for(int i=0;i<=k+1;++i) Add(ret,a[0][i]);
return ret;
}
friend inline matrix operator*(const matrix &a,const matrix &b){
matrix c;
for(int i=0;i<=k+1;++i)
for(int l=0;l<=k+1;++l)
for(int j=0;j<=k+1;++j)
Add(c.a[i][j],mul(a.a[i][l],b.a[l][j]));
return c;
}
friend inline matrix operator^(matrix a,ll b){
matrix c(1);
for(;b;b>>=1,a=a*a) if(b&1) c=c*a;
return c;
}
}A;
inline void prework(){
fac[0]=1;
for(int i=1;i<N;++i) fac[i]=mul(fac[i-1],i);
ifac[N-1]=quickpow(fac[N-1],mod-2);
for(int i=N-2;~i;--i) ifac[i]=mul(ifac[i+1],i+1);
}
int main(){
cin>>n>>k,prework(),A.init(k);
if(n==1) return puts("1"),0;
printf("%d\n",add(quickpow(n%mod,k),(A^(n-2)).getval()));
}