Description

Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + … + Ak.

Input

The input contains exactly one test case. The first line of input contains three positive integers n (n ≤ 30), k (k ≤ 109) and m (m < 104). Then follow n lines each containing n nonnegative integers below 32,768, giving A’s elements in row-major order.

Output

Output the elements of S modulo m in the same way as A is given.

Sample Input

2 2 4
0 1
1 1

Sample Output

1 2
2 3
解题思路:等比矩阵求和,采用递归二分的方法。

上图就给出了求前k项等比矩阵的和的递推式,解法采用递归来求和比较直观,也很好理解。
AC代码(1704ms):
 #include<iostream>
#include<cstring>
using namespace std;
const int maxn=;
int n,k,mod;
struct Matrix{int m[maxn][maxn];}init;
Matrix add(Matrix a,Matrix b){//矩阵加法
Matrix c;
for(int i=;i<n;++i)
for(int j=;j<n;++j)
c.m[i][j]=(a.m[i][j]+b.m[i][j])%mod;
return c;
}
Matrix mul(Matrix a,Matrix b){//矩阵乘法
Matrix c;
for(int i=;i<n;i++){
for(int j=;j<n;j++){
c.m[i][j]=;
for(int k=;k<n;k++)
c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
}
}
return c;
}
Matrix quick_power(Matrix a,int x){//矩阵快速幂
Matrix b;memset(b.m,,sizeof(b.m));
for(int i=;i<n;++i)b.m[i][i]=;//单位矩阵
while(x){
if(x&)b=mul(b,a);
a=mul(a,a);x>>=;
}
return b;
}
Matrix sum(Matrix s,int k){//求前k项和
if(k==)return s;//递归出口:当幂指数为1时,返回当前的矩阵
Matrix tmp;memset(tmp.m,,sizeof(tmp.m));//暂存保存中间的矩阵
for(int i=;i<n;++i)tmp.m[i][i]=;//单位矩阵
tmp=add(tmp,quick_power(s,k>>));//计算1+A^{k/2}
tmp=mul(tmp,sum(s,k>>));//计算(1+A^{k/2})*(A + A^2 + A^3 + … + A^{k/2})=(1+A^{k/2})*(S_{k/2})
if(k&)tmp=add(tmp,quick_power(s,k));//若k是奇数,则加上A^k
return tmp;//返回前k项的值
}
void print_rectangle(Matrix r){
for(int i=;i<n;++i)
for(int j=;j<n;++j)
cout<<r.m[i][j]<<((j==n-)?"\n":" ");
}
int main(){
while(cin>>n>>k>>mod){
for(int i=;i<n;++i)
for(int j=;j<n;++j)
cin>>init.m[i][j];
init=sum(init,k);
print_rectangle(init);
}
return ;
}

采用分块矩阵求解可以减少很多时间,具体推导可以结合下图:

矩阵中套矩阵,效率上比上一种方法更快,实际上是2n×2n的矩阵快速幂。就样例展开等式左边的矩阵:

那么最终的答案就是等式右边矩阵中左下角的子矩阵减去单位矩阵,注意某个元素值减-1之后可能为-1,那么此时只需再加上mod即可。

AC代码(610ms):

 #include<iostream>
#include<cstring>
using namespace std;
const int maxn=;
struct Matrix{int m[maxn][maxn];}init;
int n,k,mod;
Matrix mul(Matrix a,Matrix b){//矩阵乘法
Matrix c;
for(int i=;i<*n;i++){//矩阵大小扩大两倍,枚举第一个矩阵的行
for(int j=;j<*n;j++){//枚举第二个矩阵的列
c.m[i][j]=;
for(int k=;k<*n;k++)//枚举第一个矩阵的列
c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
}
}
return c;
}
Matrix POW(Matrix a,int x){//矩阵快速幂
Matrix b;memset(b.m,,sizeof(b.m));
for(int i=;i<*n;++i)b.m[i][i]=;//构造单位矩阵
while(x){
if(x&)b=mul(b,a);
a=mul(a,a);x>>=;
}
return b;
}
void print_rectangle(Matrix r){
for(int i=;i<n;++i){
for(int j=;j<n;++j){
if(i==j)r.m[n+i][j]-=;
if(r.m[n+i][j]<)r.m[n+i][j]+=mod;//左下角子矩阵减去单位矩阵,减完可能小于0,因此需要加上mod再取余mod
cout<<r.m[n+i][j]<<((j==n-)?'\n':' ');
}
}
}
int main(){
while(cin>>n>>k>>mod){
memset(init.m,,sizeof(init.m));//全部初始化为0
for(int i=;i<n;++i){//首先初始化矩阵
for(int j=;j<n;++j)
cin>>init.m[i][j];
init.m[n+i][i]=init.m[n+i][n+i]=;//其余是单位矩阵
}
init=POW(init,k+);//求其前k+1项和(左下角包含单位矩阵,最后输出要减去单位矩阵)
print_rectangle(init);//打印等比矩阵A前k项和
}
return ;
}

题解报告:poj 3233 Matrix Power Series(矩阵快速幂)的更多相关文章

  1. POJ 3233 Matrix Power Series 矩阵快速幂

    设S[k] = A + A^2 +````+A^k. 设矩阵T = A[1] 0 E E 这里的E为n*n单位方阵,0为n*n方阵 令A[k] = A ^ k 矩阵B[k] = A[k+1] S[k] ...

  2. POJ 3233 Matrix Power Series 矩阵快速幂+二分求和

    矩阵快速幂,请参照模板 http://www.cnblogs.com/pach/p/5978475.html 直接sum=A+A2+A3...+Ak这样累加肯定会超时,但是 sum=A+A2+...+ ...

  3. Poj 3233 Matrix Power Series(矩阵乘法)

    Matrix Power Series Time Limit: 3000MS Memory Limit: 131072K Description Given a n × n matrix A and ...

  4. poj 3233 Matrix Power Series 矩阵求和

    http://poj.org/problem?id=3233 题解 矩阵快速幂+二分等比数列求和 AC代码 #include <stdio.h> #include <math.h&g ...

  5. poj 3233 Matrix Power Series(矩阵二分,高速幂)

    Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 15739   Accepted:  ...

  6. POJ 3233:Matrix Power Series 矩阵快速幂 乘积

    Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 18450   Accepted:  ...

  7. POJ3233 Matrix Power Series 矩阵快速幂 矩阵中的矩阵

    Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 27277   Accepted:  ...

  8. POJ3233:Matrix Power Series(矩阵快速幂+二分)

    http://poj.org/problem?id=3233 题目大意:给定矩阵A,求A + A^2 + A^3 + … + A^k的结果(两个矩阵相加就是对应位置分别相加).输出的数据mod m.k ...

  9. POJ 3233 Matrix Power Series(矩阵高速功率+二分法)

    职务地址:POJ 3233 题目大意:给定矩阵A,求A + A^2 + A^3 + - + A^k的结果(两个矩阵相加就是相应位置分别相加).输出的数据mod m. k<=10^9.     这 ...

  10. POJ 3233 Matrix Power Series(矩阵等比求和)

    题目链接 模板题. #include <cstdio> #include <cstring> #include <iostream> #include <ma ...

随机推荐

  1. python3返回值中的none

    浏览器返回null,python3返回none,懵了. google了很多资料,不明就里,这就是没基础的后果啊呀呀呀. 上阮一峰的截图,就这么理解下凑合吧:

  2. 邓_ HTML+CSS·经常使用的设计方法

    :WPA;P:hejia,888?;S:Hejia666; https://github.com/qq1415551519 HTML+CSS·经常使用的设计方法: ================== ...

  3. Ioc思想

    DIP: Dependency Inversion Principle 依赖倒转原则 高层次组件不应该依赖于低层次组件,二者均应该依赖于接口.抽象不应该依赖于细节,细节应该依赖于抽象. IOC:Inv ...

  4. Android layer-list(1)

     Android layer-list(1) Android layer-list,顾名思义,实现列表组合后形成的图层,写一个例子. activity_main.xml文件: <?xml v ...

  5. POJ 2065 高斯消元求解问题

    题目大意: f[k] = ∑a[i]*k^i % p 每一个f[k]的值就是字符串上第 k 个元素映射的值,*代表f[k] = 0 , 字母代表f[k] = str[i]-'a'+1 把每一个k^i求 ...

  6. - > 最大公约数(辗转相除法)和最小公倍数(公式法)

    最大公约数 #include<iostream> using namespace std; int a,b; int gcd(int x,int y){ return x==0?y:gcd ...

  7. 用ZooKeeper做为注册中心搭建基于Spring Cloud实现服务注册与发现

    前提: 先安装好ZooKeeper的环境,搭建参考:http://www.cnblogs.com/EasonJim/p/7482961.html 说明: 可以再简单的理解为有两方协作,一个是服务提供这 ...

  8. cocos2d-x大版本号3.1系列一

    本人博客,欢迎转载:http://blog.csdn.net/dawn_moon 项目忙完了.继续写我的博客.去cocos2d-x的官网看了下,不出所料.又有惊喜啊.3.0经过几个版本号的迭代,最终迎 ...

  9. Username is not in the sudoers file. This incident will be reported

    type sudo adduser <username> sudo where username is the name of the user you want to add in th ...

  10. 1.4-动态路由协议OSPF④

    多区域的OSPF: 划分多区域的主要目的: 1.减少每个区域中的路由条目,进而减少每个路由器的内存中的路由,及其内存消耗,提高转发效率. 2.因为每一个OSPF区域对应在一个OSPF LSDB,配合在 ...