您的位置:首页 > 其它

Fibonacci数列的矩阵运算

2014-04-16 21:36 162 查看
Fibonacci数列这一族的ACM层出不穷,屡屡坑爹,每次好容易看出是它结果又死在O(n)算法上

下面贴出来的是Fibonacci数列的O(log n)的矩阵算法

# include <iostream>

typedef long long LL;

typedef struct VALUEPAIR
{
LL PreviousVal;
LL PresentVal;
VALUEPAIR(const LL & x1, const LL & x2)
{
PreviousVal = x1;
PresentVal = x2;
}
}ValuePair, VP;

class Matrix
{
public:
Matrix();
Matrix(const Matrix &);
const Matrix operator=(const Matrix &);
~Matrix();
//void selfMutiply();
void operator*=(const Matrix &);
LL getLtV() const;
LL getLdV() const;
LL getRtV() const;
LL getRdV() const;
VP operator*(const VP &);
Matrix operator*(const Matrix &);
friend std::ostream & operator<<(std::ostream &, const Matrix &);
private:
LL ltVal, rtVal, ldVal, rdVal;
};

Matrix calculate(const int &);
void getAns(const int &);

int main(int argc, char const *argv[])
{
int nTime = 0;
while(1)
{
VP vp(0, 1);
std::cout << "Input an integer pls\nnTime : ";
while((std::cin >> nTime).fail())
{
std::cout << "Error input\nInput an integer pls\nnTime :";
std::cin.clear();
std::cin.sync();
}
getAns(nTime);
}
return 0;
}

Matrix calculate(const int &nTime)
{
//std::cout << nTime << std::endl;
if(nTime == 1)
{
return Matrix();
}
else
{
if(nTime % 2 == 1)
{
Matrix x, p = calculate(nTime / 2);
p *= p;
return x * p;
}
else
{
Matrix x = calculate(nTime / 2);
return x * x;
}
}
}

void getAns(const int &nTime)
{
Matrix x = calculate(nTime);
VP vp(0, 1);
vp = x * vp;
std::cout << vp.PresentVal << std::endl;
}

Matrix::Matrix()
{
this->ltVal = 0;
this->ldVal = 1;
this->rtVal = 1;
this->rdVal = 1;
}

Matrix::Matrix(const Matrix &matrix)
{
//std::cout << "copy constructor" << std::endl;
this->ltVal = matrix.ltVal;
this->ldVal = matrix.ldVal;
this->rtVal = matrix.rtVal;
this->rdVal = matrix.rdVal;
}

const Matrix Matrix::operator=(const Matrix & matrix)
{
//std::cout << "operator =" << std::endl;
this->ltVal = matrix.ltVal;
this->ldVal = matrix.ldVal;
this->rtVal = matrix.rtVal;
this->rdVal = matrix.rdVal;
return *this;
}

Matrix::~Matrix()
{

}

void Matrix::operator*=(const Matrix &matrix)
{
int ltVal, ldVal, rtVal, rdVal;
ltVal = this->ltVal * matrix.ltVal + this->rtVal * matrix.ldVal;
ldVal = this->ldVal * matrix.ltVal + this->rdVal * matrix.ldVal;
rtVal = this->ltVal * matrix.rtVal + this->rtVal * matrix.rdVal;
rdVal = this->ldVal * matrix.rtVal + this->rdVal * matrix.rdVal;
this->ltVal = ltVal;
this->ldVal = ldVal;
this->rtVal = rtVal;
this->rdVal = rdVal;
}

LL Matrix::getLtV() const
{
return this->ltVal;
}

LL Matrix::getLdV() const
{
return this->ldVal;
}

LL Matrix::getRtV() const
{
return this->rtVal;
}

LL Matrix::getRdV() const
{
return this->rdVal;
}

VP Matrix::operator*(const VP &vp)
{
LL x = vp.PreviousVal, y = vp.PresentVal;
return VP(x * this->getLtV() + y * this->getRtV(), x  * this->getLdV() + y * this->getRdV());
}

Matrix Matrix::operator*(const Matrix &matrix)
{
int ltVal, ldVal, rtVal, rdVal;
ltVal = this->ltVal * matrix.ltVal + this->rtVal * matrix.ldVal;
ldVal = this->ldVal * matrix.ltVal + this->rdVal * matrix.ldVal;
rtVal = this->ltVal * matrix.rtVal + this->rtVal * matrix.rdVal;
rdVal = this->ldVal * matrix.rtVal + this->rdVal * matrix.rdVal;
this->ltVal = ltVal;
this->ldVal = ldVal;
this->rtVal = rtVal;
this->rdVal = rdVal;
return *this;
}

std::ostream & operator<<(std::ostream &stream, const Matrix &matrix)
{
stream << matrix.getLtV() << " " << matrix.getRtV() << std::endl;
stream << matrix.getLdV() << " " << matrix.getRdV() << std::endl;
}

主要用到的思想便是矩阵的快速幂(ACM通常跟着坑爹的求模运算,这时候就看你数论的了)

这里需要提一下的就是

Matrix calculate(const int &nTime)
{
//std::cout << nTime << std::endl;
if(nTime == 1)
{
return Matrix();
}
else
{
if(nTime % 2 == 1)
{
Matrix x, p = calculate(nTime / 2);
p *= p;
return x * p;
}
else
{
Matrix x = calculate(nTime / 2);
return x * x;
}
}
}


千万不要偷懒写成

Matrix calculate(const int &nTime)
{
//std::cout << nTime << std::endl;
if(nTime == 1)
{
return Matrix();
}
else
{
if(nTime % 2 == 1)
{
Matrix x;
return x * calculate(nTime / 2) * calculate(nTime / 2);
}
else
{
return calculate(nTime / 2) * calculate(nTime / 2);
}
}
}


不然真心逗了,不如直接算的,更慢更耗空间。

而对于写类的孩纸们,这里的重写等号函数并未申请空间,当是真正的二维数组的时候,记得delete其指针和正确的析构函数,不然内存怎么爆的都不知道

const Matrix Matrix::operator=(const Matrix & matrix)
{
//std::cout << "operator =" << std::endl;
this->ltVal = matrix.ltVal;
this->ldVal = matrix.ldVal;
this->rtVal = matrix.rtVal;
this->rdVal = matrix.rdVal;
return *this;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: