01.斐波那契數列

1.解析

第一反應動態規劃,時間複雜度必然是O(N),現在有個辦法能把時間複雜度變爲O(logN),我不確定這種辦法能不能用在其它動態規劃上。遞推毫無爭議,公式如下:
F(N)=F(N1)+F(N2) F(N) = F(N-1) + F(N-2)
  書上表示出了一種矩陣的格式,我也不知道是怎麼推出的,只是說“二階遞推數列一定能夠用矩陣的乘法表示”(這不就表示所有的遞推都能用?DP大多數都是遞推的)。
(F(N),F(N1))=(F(N1),F(N2)){abcd} (F(N),F(N-1)) = (F(N-1),F(N-2)) * \left\{ \begin{matrix} a & b\\ c & d\\ \end{matrix} \right\}
  abcd用試的就能試出來具體的值
(F(3),F(2))=(1,1){1110} (F(3),F(2)) = (1,1) * \left\{ \begin{matrix} 1 & 1\\ 1 & 0\\ \end{matrix} \right\}

(F(4),F(3))=(1,1){1110}2 (F(4),F(3)) = (1,1) * \left\{ \begin{matrix} 1 & 1\\ 1 & 0\\ \end{matrix} \right\}^{2}

(F(N),F(N1))=(F(N1),F(N2)){1110}N2 (F(N),F(N-1)) = (F(N-1),F(N-2)) * \left\{ \begin{matrix} 1 & 1\\ 1 & 0\\ \end{matrix} \right\}^{N-2}

這就是新的遞推公式,問題也就轉換爲了矩陣快速冪問題。矩陣快速冪問題在別的章節講。

2.複雜度分析

時間複雜度就是將一個數字分割成二進制數後,二進制數的位數。因爲是二進制數,所以應該是logN。只是感覺是這樣,具體的證明沒有,我也有點迷糊。

3.代碼

寫的有點亂,我一方面想要進行參數判斷,一方面想要方便,藍瘦

牛客已證

#include <iostream>
#include <vector>


using namespace std;

///<矩陣乘法,a和b是兩個待乘的矩陣,c是返回值
bool multi_matrix(vector<vector<int> >a, vector<vector<int> >b, vector<vector<int> >&c)
{	
	if(a.empty() || b.empty() || c.empty())
		return false;
	vector<vector<int> >tmp(c.size(), vector<int>(c[0].size(), 0));
	c.assign(tmp.begin(), tmp.end());

	for(int i=0;i<(int)a.size();++i)
		for(int j=0;j<(int)b[0].size();++j)
			for(int k=0; k<(int)b.size();++k)
				c[i][j] += a[i][k] * b[k][j];
	return true;
}

///<矩陣快速冪乘法,m矩陣的p次冪,res是返回值,m不用引用會報段錯誤,我也不知道爲啥
bool matrix_pow(vector<vector<int> >&m, int p, vector<vector<int> >&res)
{
	if(m.empty())
		return false;

	vector<vector<int> >zero(m.size(), vector<int>(m[0].size(),0));
	res.assign(zero.begin(), zero.end());
	for(int i=0;i<(int)m.size();++i)
	{
		for(int j=0;j<(int)m[0].size();++j)	
		{
			if(i==j)
				res[i][j] = 1;
			else
				res[i][j] = 0;
		}
	}
	vector<vector<int> >tmp(m.begin(), m.end());
	while(0 != p)
	{
		if(0 != (p&1))
			multi_matrix(res,tmp,res);	
		multi_matrix(tmp,tmp,tmp);
		p>>=1;
	}
	
	return true;
}


int main(void)
{
	int a[2]={1,1};
	int b[2]={1,0};
	vector<int>c;
	c.assign(a,a+2);
	vector<int>d;
	d.assign(b,b+2);
	vector<vector<int> >e;
	e.push_back(c);
	e.push_back(d);
	vector<vector<int> >res;
	int n ;
	cin>>n;
	if(1==n || 2==n)
		cout<<1<<endl;
	else
	{
		matrix_pow(e,n-2,res);
		cout<<res[0][0]+res[1][0]<<endl;
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章