POJ月赛题目Matrix Power Series
来源:互联网 发布:idg 知乎 编辑:程序博客网 时间:2024/05/01 08:17
描述
Given a n × n matrix A anda positive integer k, find the sum S = A + A2 + A3 +… + Ak.
输入
The input contains exactly one test case. The first line ofinput contains three positive integers n (n ≤ 30), k (k ≤ 10^9) and m (m < 10^4).Then follow n lines each containing n nonnegative integers below 32,768, givingA’s elements in row-major order.
输出
Output the elements of S modulo m in the same way as A is given.
样例输入
2 2 4
0 1
1 1
样例输出
1 2
2 3
来源
POJ Monthly
算法:
先考虑以下和X= a + a2 +a3 + … + ak,即a是一个实数,求级数和X。一般有两种想法:
(1)利用霍纳(horner法则---不会的自己翻算法导论,并自觉面墙去);
(2)即利用级数和公式,可以在 O(log n)内计算。
本题目解法:
在一开始时就需要考虑到数据规模,如果使用类似horner的算法, 则复杂度是O(k * n *n*n果断到1013 的复杂度级别,果断超时,利用级数求和时,需要做除法,两矩阵的除法存在的冲要条件是矩阵为两矩阵同型,分母方阵且行列式不为0,即将除法转化为乘上分母的逆矩阵。在本题中,就算逆矩阵存在,也不一定能使用这种算法计算出结果,因为要计算行列式的值,30 * 30的行列式的值,目前并没有什么靠谱的简单算法能快速计算。
大家都知道计算两个复数(a+bi)与(c+di)的乘积,一般的算法是使用定义,即使用4次乘法就OK。不知道大家是否还记得算法导论上有个题目,即只使用3次乘法去计算两个复数的积,算法大致如下:先计算a*c、b*d、(a+b)*(c+d),显然,这三个乘积足够推导出(a+bi)*(c+di)的值。 在本题中,一样可使用类似的拆项技巧,S = A + A2 + A3 +… + Ak, 设E 为单位方阵,考虑S+E=A0+A1+ A2 + A3 +… + Ak,当k = 3时,我们只需要计算(E+A)*(E+A2),当k = 7 时,我们只需要计算(E+A)*(E+A2)*(E+A3),对于1、3、7、15...这种特殊的k,我们可以速度地计算出来,但是,对于一般的k,我们能怎么办呢?答案很简单,拆项...,比如k=13,拆成
S+E=A0+A1+ A2 + A3 +… + A13 = (E+A)*(E+A2)*(E+A3)+ A8(E+A)*(E+A2)+A12(E+A)...
写出这个式子 的时候,相信大家都明白了,求值时,我们只需要先在O(log k * n * n * n)的时间复杂度内预先计算几个矩阵的值,然后可地推地把k减小,直到0(每次至少减一半)。于是,关于递归时间复杂度有如下的递推
T(n,k) = T(k/2) + O( n * n * n),由主定理知:递归时间O(log k * n * n * n),再加上预处理矩阵的时间,总时间仍然是O(log k * n * n * n),根据题目给的数据,该复杂度肯定可以接受,以下是代码:
<span style="font-size:18px;">#include <cstdlib>#include <cstring>#include <algorithm>#include <iostream>using namespace std; #ifdef _MSC_VERtypedef __int64 lld;#elsetypedef long long lld;#endif class Matrix{public: Matrix(); Matrix(const Matrix& rhs);public: friend istream& operator >>(istream& in, Matrix& rhs);public: Matrix& operator *= (const Matrix&rhs); friend const Matrix operator * (constMatrix& lhs, const Matrix& rhs); friend Matrix MakeIndenty(const lldiScale); Matrix& operator = (const Matrix&rhs); Matrix& operator ^= (lld Exp); Matrix& operator %= (lld Mod); Matrix& operator -=(const Matrix&rhs); Matrix& operator += (const Matrix&rhs); friend const Matrix operator % (constMatrix& lhs, const lld Mod); friend Matrix operator ^ (const Matrix& lhs, const lld Exp);public: lld m_Element[30][30]; lld m_iScale;}; lld Mod, iScale, Exp; //power matrixMatrix PM[32];Matrix PME[32];Matrix PMEMul[32];//matrix explld exp[32]; Matrix&Matrix::operator-=(const Matrix& rhs){ lld iScale = m_iScale; for(int r= 0; r < iScale; ++r){ for(int c = 0; c< iScale ;++c){ m_Element[r][c] -=rhs.m_Element[r][c]; m_Element[r][c] += Mod; } } *this %= Mod; return *this;} Matrix& Matrix::operator +=(const Matrix& rhs){ lld iScale = m_iScale; for(int r= 0; r < iScale; ++r){ for(int c = 0; c< iScale ;++c){ m_Element[r][c] +=rhs.m_Element[r][c]; } } *this %= Mod; return *this;} Matrix operator + (constMatrix& lhs, const Matrix& rhs){ Matrix result = lhs; result += rhs; return result;} Matrix MakeIndenty(const lldiScale){ Matrix result; result.m_iScale = iScale; for(int i= 0; i< iScale; ++i){ result.m_Element[i][i] = 1; } return result;} Matrix::Matrix(){ memset(m_Element, 0, sizeof(m_Element)); m_iScale = 0;} Matrix::Matrix(const Matrix&rhs){ memcpy(m_Element, rhs.m_Element, sizeof(m_Element)); m_iScale = rhs.m_iScale;} istream& operator >>(istream& in, Matrix& rhs){ for(int r = 0; r< rhs.m_iScale; ++r){ for(int c = 0; c< rhs.m_iScale;++c){ in>>rhs.m_Element[r][c]; } } rhs %= Mod; return in;} Matrix& Matrix::operator *=(const Matrix &rhs){ lld ele[30][30]; lld iScale = m_iScale; for(int r = 0; r< iScale; ++r){ for(int c = 0; c< iScale; ++c){ ele[r][c] = m_Element[r][c]; m_Element[r][c] = 0; } } for(int r= 0; r< iScale; ++r){ for(int c= 0; c< iScale; ++c){ for(int k= 0; k< iScale; ++k){ m_Element[r][c] += ele[r][k] *rhs.m_Element[k][c]; } } } *this %= Mod; return *this;} Matrix& Matrix::operator =(const Matrix& rhs){ memcpy(m_Element, rhs.m_Element,sizeof(m_Element)); m_iScale = rhs.m_iScale; return *this;} const Matrix operator * (constMatrix& lhs, const Matrix& rhs){ Matrix result = lhs; result *= rhs; return result;} Matrix& Matrix::operator ^=(lld Exp){ if(Exp == 1){ //empty }else if(!Exp){ *this = MakeIndenty(m_iScale); }else{ Matrix xx = *this; xx^=(Exp>>1); xx*=xx; if(Exp & 1){ xx*=*this; } *this = xx; } *this %= Mod; return *this;} Matrix operator ^ (constMatrix& lhs, const lld Exp){ Matrix xx = lhs; xx^=Exp; return xx;} Matrix& Matrix::operator %=(lld Mod){ lld iScale = m_iScale; for(int r = 0; r< iScale; ++r){ for(int c = 0; c< iScale; ++c){ m_Element[r][c] %= Mod; } } return *this;} const Matrix operator % (constMatrix& lhs, const lld Mod){ Matrix xx = lhs; xx %= Mod; return xx;} Matrix Solve(const Matrix&PreFix, const lld k); int main(){ cin>>iScale>>Exp>>Mod; PM[0].m_iScale = iScale; cin>>PM[0]; for(int i= 1; i<= 31; ++i){ PM[i] = PM[i-1] * PM[i-1]; } for(int i= 0; i<= 31; ++i){ PME[i] = PM[i]; PME[i] += MakeIndenty(iScale); } exp[0] =1; for(int i= 1; i< 31; ++i){ exp[i] = (exp[i-1] << 1) + 1; } PMEMul[0] = PME[0]; for(int i= 1; i< 31; ++i){ PMEMul[i] = PME[i] * PMEMul[i-1]; } cout<<endl<<endl; Matrix result = Solve(MakeIndenty(iScale),Exp); result -= MakeIndenty(iScale); for(int r = 0; r< iScale; ++r){ for(int c = 0; c< iScale; ++c){ cout<<result.m_Element[r][c]<<' '; } cout<<endl; } } Matrix Solve(const Matrix&PreFix, const lld k){ if(k == 1){ return PreFix * PMEMul[0]; } lld idx = (lower_bound(exp, exp + 32, k) -exp); --idx; lld left = k - (1<<(idx+1)); if(left == 0){ return PreFix * PMEMul[idx] + PreFix *PM[idx + 1]; }else if(left < 0){ return PreFix * PMEMul[idx]; } return PreFix * PMEMul[idx] + Solve(PreFix* PM[idx + 1], left);}</span>
以下是OJ运行结果截图:
- POJ月赛题目Matrix Power Series
- poj Matrix Power Series
- Matrix Power Series POJ
- POJ 3233 Matrix Power Series
- POJ 3233Matrix Power Series
- poj 3233 Matrix Power Series
- poj 3233 Matrix Power Series
- Poj 3233 Matrix Power Series
- POJ 3233 Matrix Power Series
- [POJ]3233. Matrix Power Series
- poj 3233 Matrix Power Series
- poj 3233 Matrix Power Series
- POJ 3233 Matrix Power Series
- poj 3233 Matrix Power Series
- poj 3233 Matrix Power Series
- poj 3233 Matrix Power Series
- POJ 3233 Matrix Power Series
- poj 3233:Matrix Power Series
- 在retina屏中实现1px border效果
- PhantomJS基础及示例
- jquery 选择器写法
- 多线程
- QTP\UFT11.5破解
- POJ月赛题目Matrix Power Series
- Language of FatMouse(trie树)
- sql server FOR XML PATH 字符串拼接
- cocos2dx 利用CCOrbitCamera实现扑克牌翻牌效果
- aboutme
- Android--Dialog详细讲解
- blog-for-pluspower
- windows下使用GUI 把本地代码提交到git远程仓库
- 方向