考点
题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e4;
void mulself(ll a[2][2]) { ll t[2][2]; memset(t, 0, sizeof(t)); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { for (int k = 0; k < 2; ++k) { t[i][j] = (t[i][j] + a[i][k] * a[k][j]) % mod; } } } memcpy(a, t, sizeof(t)); }
void mul(ll f[2], ll a[2][2]) { ll t[2]; memset(t, 0, sizeof(t)); for (int i = 0; i < 2; ++i) { for (int k = 0; k < 2; ++k) { t[i] = (t[i] + f[k] * a[k][i]) % mod; } } memcpy(f, t, sizeof(t)); }
int main() { int n; while (cin >> n && ~n) { ll f[2] = {0, 1}, a[2][2] = {{0, 1}, {1, 1}}; while (n) { if (n & 1) mul(f, a); mulself(a); n >>= 1; } cout << f[0] << endl; } return 0; }
|
思路
递推时只保存最近的两个斐波那契数,即可得到下一个斐波那契数。
设\(F\left( n
\right)\)表示一个1 * 2
的矩阵,\(F\left( n \right) =\left[ Fib_n\,\,Fib_{n+1}
\right]\),
我们希望根据\(F\left( n-1 \right) =\left[
Fib_{n-1}\,\,Fib_n \right]\)计算出\(F\left( n \right)\),
构造一个矩阵A
,设计如下矩阵乘法: \[
F\left( n \right) =F\left( n-1 \right) \cdot A\Longleftrightarrow \left[
Fib_n\,\,Fib_{n+1} \right] =\left[ Fib_{n-1}\,\,Fib_n \right] \cdot
\left[ \begin{matrix}
0& 1\\
1& 1\\
\end{matrix} \right]
\] 根据题意,初值为\(F\left( 0 \right)
=\left[ 0 1 \right]\),目标为\(F\left(
n \right) =F\left( 0 \right) \cdot A^n\)
由于矩阵乘法满足结合律,所以可以用快速幂计算上述式子,得到的矩阵第1列上的数就是\(Fib_n\)