题目大意:
f(i) 是一个斐波那契数列 , 求sum(f(i)^k)的总和
由于n极大,所以考虑矩阵快速幂加速
我们要求解最后的sum[n]
首先我们需要思考
sum[n] = sum[n-1] + f(i+1)^k
那么很显然sum[n-1]是矩阵中的一个元素块
那么f(i+1)^k怎么利用f(i) , f(i-1)来求
f(i+1)^k = (f(i) + f(i-1)) ^ k
假如k = 1 , 可以看出f(i+1) = f(i-1) + f(i) (1,1)
k = 2 , 可以看出f(i+1)^2 = f(i-1)^2 + 2*f(i-1)*f(i) + f(i)^2 (1 , 2 , 1)
后面只列出前面的因子 k=3 1 , 3 , 3 , 1
k =4 1, 4 ,6,4,1
很容易看出后一行的数是由前一行的数当前列和前一列的相加
那么这里要放入矩阵中思考的就是 f(i-1)^k , f(i-1)^(k-1)*f(i) ...... f(i)^k , sum[i] 这样 k+2 个元素
那么做矩阵快速幂就是利用f(i-1)^k , f(i-1)^(k-1)*f(i) ...... f(i)^k , sum[i] 乘以某一个矩阵得到
f(i)^k , f(i)^(k-1)*f(i+1) ...... f(i+1)^k , sum[i+1]
自己一个个递推就会渐渐利用上述的关系轻松得到这个矩阵
1 #include <cstdio> 2 #include <cstring> 3 4 using namespace std; 5 #define N 100 6 #define ll long long 7 const int MOD = 1000000007; 8 int n , k , l; 9 int num[N]; 10 11 struct Matrix{ 12 int a[N][N]; 13 Matrix operator*(const Matrix &m) const{ 14 Matrix ans ; 15 for(int i=0 ; i<l ; i++){ 16 for(int j=0 ; j<l ; j++){ 17 ans.a[i][j] = 0; 18 for(int k=0 ; k<l ; k++){ 19 ans.a[i][j] += ((ll)a[i][k] * m.a[k][j])%MOD; 20 ans.a[i][j] %= MOD; 21 } 22 } 23 } 24 return ans; 25 } 26 }st; 27 28 Matrix q_pow(Matrix b , int t) 29 { 30 Matrix ans; 31 memset(ans.a , 0 , sizeof(ans)); 32 for(int i=0 ; i<l ; i++) ans.a[i][i] = 1; 33 while(t) 34 { 35 if(t&1) ans = ans*b; 36 b = b*b; 37 t>>=1; 38 } 39 return ans; 40 } 41 42 void build_matrix() 43 { 44 memset(st.a , 0 , sizeof(st.a)); 45 st.a[l-2][0] = 1; 46 for(int i=1 ; i<l-1 ; i++){ 47 for(int j=l-2 , t=0 ; t<=i ; t++,j--){ 48 st.a[j][i] = st.a[j][i-1]+st.a[j+1][i-1]; 49 } 50 } 51 for(int i=0 ; i<l-1 ; i++) 52 st.a[i][l-1] = st.a[i][l-2]; 53 st.a[l-1][l-1] = 1; 54 } 55 56 int main() 57 { 58 #ifndef ONLINE_JUDGE 59 freopen("a.in" , "r" , stdin); 60 #endif // ONLINE_JUDGE 61 int T; 62 scanf("%d" , &T); 63 while(T--) 64 { 65 scanf("%d%d" , &n , &k); 66 l = k+2; 67 build_matrix(); 68 for(int i=0 ; i<l-1 ; i++){ 69 num[i] = 1; 70 } 71 num[l-1] = 2; 72 if(n<=2) printf("%d\n" , n); 73 else{ 74 Matrix ans = q_pow(st , n-2); 75 int ret = 0; 76 for(int i=0 ; i<l ; i++){ 77 ret += num[i]*ans.a[i][l-1]%MOD; 78 ret %= MOD; 79 } 80 printf("%d\n" , ret); 81 } 82 } 83 return 0; 84 }