⎨ ⎧ a , b , A ⋅ F ( n − 1 ) + B ⋅ F ( n − 2 ) + C , n = 1 n = 2 n ≥ 3 那么,矩阵与Fibonacci有什么关系呢?
其实关系有许多,这里仅提供一种关系,如下:
因此,我们甚至可以通过矩阵求幂的方法 ,算出fibonacci sequence 的第n项!
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <algorithm> using namespace std;const int mod = 1e9 + 7 ;struct Node { long long mat[2 ][2 ]; Node (){} Node (long long a_, long long b_, long long c_, long long d_) { mat[0 ][0 ] = a_; mat[0 ][1 ] = b_; mat[1 ][0 ] = c_; mat[1 ][1 ] = d_; } Node operator *(const Node &y) { Node x (0 ,0 ,0 ,0 ) ; for (int i = 0 ; i <= 1 ; i++){ for (int j = 0 ; j <= 1 ; j++){ for (int k = 0 ; k <= 1 ; k++){ x.mat[i][j] = x.mat[i][j]%mod + ((this ->mat[i][k]%mod)*(y.mat[k][j]%mod))%mod; x.mat[i][j] %= mod; } x.mat[i][j] %= mod; } } return x; } }; Node Pow (Node a, int n) { Node x (1 ,0 ,0 ,1 ) ; while (n > 0 ){ if (n&1 ) x = x*a; n = n >> 1 ; a = a*a; } return x; } int main () { int n; while (scanf ("%d" , &n) != EOF) { Node x (1 ,1 ,1 ,0 ) ; Node ans = Pow (x, n); printf ("%lld\n" ,ans.mat[0 ][1 ]); } return 0 ; }
此外,对于 类斐波那契数列 也有类似的关系:
我们花这么多篇幅讲这个,有什么含义呢?事实上,ACM中,将fibonacci和取模运用起来,出了一些典型的题目
经典例题 Number Sequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 243613 Accepted Submission(s): 62051
Problem Description
A number sequence is defined as follows:
f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.
Given A, B, and n, you are to calculate the value of f(n).
Input
The input consists of multiple test cases. Each test case contains 3 integers A, B and n on a single line (1 <= A, B <= 1000, 1 <= n <= 100,000,000). Three zeros signal the end of input and this test case is not to be processed.
Output
For each test case, print the value of f(n) on a single line.
Sample Input
Sample Output
很明显,这道题将我们前面所学到的知识:模运算、快速幂、矩阵快速幂、斐波那契数列 全部融合在一起了,那么,你能解决这道题了吗?
如果,你以为本文章就这么结束了,那么你就错了!
这道题,如果用到前面这些知识,代码量大,数据多,难以处理。那么我们还能用学过的什么来解决这个问题呢?
循环节问题|点击跳转
由于所求结果都是 mod 7.那么,答案就在 0~6 这个区间内!!!
而由斐波那契数列的定义我们知道,F(n)需要由F(n-1)和F(n-2)共同决定.
由组合数学的相关知识,结果有C 7 1 ⋅ C 7 1 = 49 C^1_7 ·C^1_7 = 49 C 7 1 ⋅ C 7 1 = 49 种组合(也可以看成是7进制数由00~66的个数),我们仅需枚举将前50个结果保存后,按需取出并输出即可。
AC code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> #include <stdio.h> #include <string.h> int main () { using namespace std; int n,d[1000 ],i,a,b; while (cin >> a >> b >> n && n){ if (a == 0 && b == 0 && n == 0 ) return 0 ; for (i=1 ;i<=49 ;i++){ if (i==1 ) d[i]=1 ; else if (i==2 ) d[i]=1 ; else d[i]=(a*d[i-1 ]+b*d[i-2 ])%7 ; } printf ("%d\n" ,d[n%49 ]); } return 0 ; }
等等,事实真的是这样吗?
这个问题确实可以通过循环节来做,但是实际情况中,一定是第一个结果一定在循环内部吗?
说得简单点:1、2、3、6、7、8、9、6、7、8、9、6、7、8、9
上述数据中,循环体是 6、7、8、9,而1、2、3并不包含在内哦。
同理,我们七七四十九,是否把范围缩小了呢?
建议看看这篇文章,找寻答案:https://donghuangzhong.github.io/2020/02/09/HDU-1005/
全文·完
参考资料 1.Rightmost Digit|HDOJ1061
2.快速幂算法|CSDN
3.矩阵快速幂算法|CSDN
4.斐波那契数列|百度百科
5.Number Sequence|HDOJ1005
6.HDU-1005解答|Hexo博客