package Fibonacci
import "testing"
/*
求菲波那切数列矩阵乘法的方法
1. 斐波那契数列的现行求解O(N)的方式非常好理解
2. 同时利用线性代数,可也以改写出另一种表示
|F(N),F(N-1)| = |F(2),F(1)| * 某个二阶矩阵的N-2次方
3. 求出这个二阶矩阵,进而最快求出这个二阶矩阵的N-2次方
推广:矩阵的快速幂
| a b |
|F(3),F(2)| = |F(2), F(1)| * | |
| c d |
2a+ c = 3
2b + d = 2
| a b |
|F(4),F(3)| = |F(3), F(2)| * | |
| c d |
| a b |
|F(5),F(4)| = |F(4), F(3)| * | |
| c d |
| a b |
|2,1| = |1, 1| * | |
| c d |
1*a + 1*c = 2
1*b + 1&d = 1
{ a + c = 2
{ b + d = 1
*/
func f1(n int) int { //暴力方法
if n < 1 {
return 0
}
if n == 1 || n == 2 {
return 1
}
return f1(n-1) + f1(n-2)
}
func f2(n int) int { //线性方法
if n < 1 {
return 0
}
if n == 1 || n == 2 {
return 1
}
res, pre, tmp := 1, 1, 0
for i := 3; i <= n; i++ {
tmp = res
res = res + pre
pre = tmp
}
return res
}
func TestFib(t *testing.T) {
t.Log(f1(10))
t.Log(f2(10))
t.Log(f3(10))
}
func f3(n int) int { // 矩阵方法
if n < 1 {
return 0
}
if n == 1 || n == 2 {
return 1
}
base := [][]int{
{1,1},
{1,0},
}
res := matrixPower(base, n-2)
return res[0][0] + res[1][0]
}
func matrixPower(m [][]int,p int) [][]int {
res := make([][]int,len(m))
for k := range res {
res[k] = make([]int,len(m[k]))
}
for i := 0; i < len(res); i++ {
res[i][i] = 1
}
//res = 矩阵中的1
tmp := m // 矩阵1次方
for ;p != 0 ; p >>= 1 {
if p & 1 != 0 {
res = muliMatrix(res,tmp)
}
tmp = muliMatrix(tmp,tmp)
}
return res
}
// 两个矩阵乘完之后的结果返回
func muliMatrix(m1, m2 [][]int) [][]int {
res := make([][]int,len(m1))
for k := range res {
res[k] = make([]int,len(m2[0]))
}
for i := 0; i < len(m1); i++ {
for j := 0; j < len(m2[0]); j++ {
for k := 0; k < len(m2); k++ {
res[i][j] += m1[i][k] * m2[k][j]
}
}
}
return res
}
/*
推广
满足 F(n) = C1F(n-1) + C2F(n-2) +... + CZF(n-k)
可以控制在 logN级别
奶牛问题
农场第一年 1只
每只母牛 1年可以产 1只母奶牛
小母牛 3年能开始生
满足递推公式
F(N) = F(N-1) + F(N-3)
*/
/*
上楼梯 n层台阶
人 一次 1步,2步,5步
f(n) = f(n-1) + f(n-2) + f(n-5)
*/
/*
题目四
给定一个数 N,想象只由0和1两种字符组成的所有长度为N的字符串
如果某个字符串,任何0字符的左边都有1紧挨着,认为这个字符串达标
返回有多少达标的字符串
N = 1
"0" ”1“ 1个
N = 2 "00" "01" "10" "11" 2个
N = 3 "000" "001" "010" "011" "100" "101" "110" "111" 3个
f(i) 枚举0位置 下位置不能填0 只能填1
斐波那契问题,从左往右的尝试
*/
/*
区域 2 * N
给你 1 * 2的瓷砖,有多少种方法
*/