2018年湘潭大學程式設計競賽 G題 矩陣快速冪
阿新 • • 發佈:2018-12-25
連結:https://www.nowcoder.com/acm/contest/105/G
來源:牛客網
又見斐波那契
時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld
題目描述
這是一個加強版的斐波那契數列。
給定遞推式
求F(n)的值,由於這個值可能太大,請對109+7取模。
輸入描述:
第一行是一個整數T(1 ≤ T ≤ 1000),表示樣例的個數。
以後每個樣例一行,是一個整數n(1 ≤ n ≤ 1018)。
輸出描述:
每個樣例輸出一行,一個整數,表示F(n) mod 1000000007。
示例1
輸入
複製
4
1
2
3
100
輸出
複製
1
16
57
558616258
思路:
我們構造一個矩陣D = {
{0,1,0,0,0,0},
{1,1,0,0,0,0},
{0,1,1,0,0,0},
{0,4,3,1,0,0},
{0,6,3,2,1,0},
{0,4,1,1,1,1}
};
(i + 1) ^ 3 + (i + 1) ^2 + (i + 1) + 1 = x^3 + 4x^2 + 6x + 4
用這個矩陣來加速 A = {f0,f1,1,1,1,1},於是 fn = A * D ^ ( n - 1 ) [0][1];
程式碼:
#include<bits/stdc++.h> using namespace std; #define ll long long const ll mod = 1e9 + 7; const int N = 6; struct Matrix { int n; ll d[6][6]; void init(int n) { this -> n = n; memset(d,0,sizeof(d)); } Matrix operator *(Matrix &b) { Matrix ans; ans.init(n); for (int i = 0;i < n;i ++) for (int j = 0;j < n;j ++) for (int k = 0;k < n;k ++) ans.d[i][j]=(ans.d[i][j]+d[i][k]*b.d[k][j])%mod; return ans; } }; ll a[N][N] = { {0,1,0,0,0,0}, {1,1,0,0,0,0}, {0,1,1,0,0,0}, {0,4,3,1,0,0}, {0,6,3,2,1,0}, {0,4,1,1,1,1} }; ll b[6] = {0,1,1,1,1,1}; Matrix quick(Matrix a,ll b) { Matrix res; res.init(a.n); for (int i = 0;i < res.n;i ++) res.d[i][i] = 1; while (b) { if (b & 1) res = res * a; a = a * a; b >>= 1; } return res; } int main() { ll t,n; scanf("%lld",&t); while (t --) { scanf("%lld",&n); if (n < 2) { printf("%lld\n",n); continue; } Matrix x,ans; x.init(6),ans.init(6); for (int i = 0;i < N;i ++) for (int j = 0;j < N;j ++) x.d[i][j] = a[i][j]; for (int i = 0;i<N;i++) ans.d[0][i]=b[i]; x = quick(x,n - 1); ans = ans * x; printf("%lld\n",ans.d[0][1]); } return 0; }