[ACM] POJ 3233 Matrix Power Series (求矩阵A+A^2+A^3...+A^k,二分求和或者矩阵转化)
| Time Limit: 3000MS | Memory Limit: 131072K | |
| Total Submissions: 15417 | Accepted: 6602 |
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
Source
field=source&key=POJ+Monthly--2007.06.03" style="text-decoration:none">POJ Monthly--2007.06.03
, Huang, Jinsong解题思路:
第一种方法:
题意为给定矩阵A(以下代码中用ori表示)。以及k, mod ,求 A+A^2+A^3+......A^k 的和对mod取余。
一開始用循环k次,递推的做法,超时。
。。
看了解题报告,求和的时候要用到二分求和。
所求的和用s(k)表示。
当k为偶数时:
比方 k=6,那么 A+A^2+A^3+A^4+A^5+A^6= A+A^2+A^3+ A^3*(A+A^2+A^3)
s(k)=s(k/2)+A^(n/2) * s(k/2) 即s(k)=(E+A^(n/2))*s(n/2) (E为单位矩阵)
当k为奇数时:
s(k)=s(k-1)+A^k , 那么k-1为偶数。能够依照上面的二分
PS:代码要写细致啊,否则一个小错误查半天.....计算两个矩阵相乘时ret.arr[i][j]+=a.arr[i][k]*b.arr[k][j]; 居然写成了ret.arr[i][j]+=a.arr[i][k]*a.arr[k][j]; T T
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int maxn=31;
int n,k,mod; struct mat
{
int arr[maxn][maxn];
mat()
{
memset(arr,0,sizeof(arr));
}
}; mat mul(mat a,mat b)
{
mat ret;
for(int i=0;i<n;i++)
for(int k=0;k<n;k++)
{
if(a.arr[i][k])
for(int j=0;j<n;j++)
{
ret.arr[i][j]+=a.arr[i][k]*b.arr[k][j];
if(ret.arr[i][j]>=mod)
ret.arr[i][j]%=mod;
}
}
return ret;
} mat add(mat a,mat b)
{
mat an;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
an.arr[i][j]=a.arr[i][j]+b.arr[i][j];
if(an.arr[i][j]>=mod)
an.arr[i][j]%=mod;
}
return an;
} mat power(mat p,int k)
{
if(k==1) return p;
mat e;
for(int i=0;i<n;i++)
e.arr[i][i]=1;
if(k==0) return e;
while(k)
{
if(k&1)
e=mul(p,e);
p=mul(p,p);
k>>=1;
}
return e;
} void output(mat ans)
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(j==n-1)
cout<<ans.arr[i][j]<<endl;
else
cout<<ans.arr[i][j]<<" ";
}
} mat cal(mat ori,int k)
{
if(k==1) return ori;
if(k&1)
return add(cal(ori,k-1),power(ori,k));//当k为奇数时,减1变为偶数 S(K)=S(K-1)+ori^K
else
return mul(add(power(ori,0),power(ori,k>>1)),cal(ori,k>>1));
//当K为偶数时,S(K)=(1+ori^(K/2))*S(K/2)
} int main()
{
while(scanf("%d%d%d",&n,&k,&mod)!=EOF)
{
mat ori,ans;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
scanf("%d",&ori.arr[i][j]);
if(ori.arr[i][j]>=mod)
ori.arr[i][j]%=mod;
}
ans=cal(ori,k);
output(ans);
}
return 0;
}
另外一种方法:
解题思路转载自:http://www.cnblogs.com/jiangjing/archive/2013/05/28/3103336.html
分析:求a^1+..a^n这是矩阵乘法中关于等比矩阵的求法:
|A E|
|0 E|
当中的A为m阶矩阵。E是单位矩阵,0是零矩阵。而我们要求的是:
A^1+A^2+..A^L。由等比矩阵的性质
|A , 1| |A^n , 1+A^1+A^2+....+A^(n-1)|
|0 , 1| 的n次方等于|0 , 1 |
所以我们仅仅须要将A矩阵扩大四倍,变成如上形式的矩阵B。然后开L+1次方就能够得到1+A^1+A^2+....+A^L。
因为多了一个1。所以最后得到的答案我们还要减去1。
同理我们把矩阵A变成B:
|A E|
|0 E|
然后我们就是求B的n+1次幂之后得到的矩阵为|x1 x2|
|x3 x4|
右上角的矩阵x2减去单位矩阵E,得到就是要求的矩阵了。
#include <iostream>
#include <string.h>
using namespace std;
const int maxn=62;
int n,k,mod; struct mat
{
int arr[maxn][maxn];
mat()
{
memset(arr,0,sizeof(arr));
}
}; mat mul(mat a,mat b)
{
mat ans;
for(int i=0;i<n;i++)
for(int k=0;k<n;k++)
{
if(a.arr[i][k])
for(int j=0;j<n;j++)
{
ans.arr[i][j]+=a.arr[i][k]*b.arr[k][j];
if(ans.arr[i][j]>=mod)
ans.arr[i][j]%=mod;
}
}
return ans;
} mat power(mat p,int k)
{
if(k==1) return p;
mat e;
for(int i=0;i<n;i++)
e.arr[i][i]=1;
if(k==0) return e;
while(k)
{
if(k&1)
e=mul(e,p);
p=mul(p,p);
k>>=1;
}
return e;
} void output(mat ans)
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(i==j)
{
ans.arr[i][j+n]--;
while(ans.arr[i][j+n]<0)
ans.arr[i][j+n]+=mod;
}
if(j==n-1)
cout<<ans.arr[i][j+n]<<endl;
else
cout<<ans.arr[i][j+n]<<" ";
}
} int main()
{
while(cin>>n>>k>>mod)
{
mat ori,ans;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
cin>>ori.arr[i][j];
if(i==j)
{
ori.arr[i][j+n]=1;
ori.arr[i+n][j+n]=1;
}
}
n*=2;
ans=power(ori,k+1);
n/=2;
output(ans);
}
return 0;
}
[ACM] POJ 3233 Matrix Power Series (求矩阵A+A^2+A^3...+A^k,二分求和或者矩阵转化)的更多相关文章
- 矩阵十点【两】 poj 1575 Tr A poj 3233 Matrix Power Series
poj 1575 Tr A 主题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1575 题目大意:A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的 ...
- POJ 3233 Matrix Power Series 【经典矩阵快速幂+二分】
任意门:http://poj.org/problem?id=3233 Matrix Power Series Time Limit: 3000MS Memory Limit: 131072K To ...
- POJ 3233 Matrix Power Series (矩阵乘法)
Matrix Power Series Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 11954 Accepted: ...
- Poj 3233 Matrix Power Series(矩阵乘法)
Matrix Power Series Time Limit: 3000MS Memory Limit: 131072K Description Given a n × n matrix A and ...
- poj 3233 Matrix Power Series(矩阵二分,高速幂)
Matrix Power Series Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 15739 Accepted: ...
- POJ 3233 Matrix Power Series(矩阵快速幂)
Matrix Power Series Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 19338 Accepted: 8161 ...
- 线性代数(矩阵乘法):POJ 3233 Matrix Power Series
Matrix Power Series Description Given a n × n matrix A and a positive integer k, find the sum S = ...
- POJ 3233 Matrix Power Series(二分等比求和)
Matrix Power Series [题目链接]Matrix Power Series [题目类型]二分等比求和 &题解: 这题我原来用vector写的,总是超时,不知道为什么,之后就改用 ...
- POJ 3233 Matrix Power Series(矩阵高速功率+二分法)
职务地址:POJ 3233 题目大意:给定矩阵A,求A + A^2 + A^3 + - + A^k的结果(两个矩阵相加就是相应位置分别相加).输出的数据mod m. k<=10^9. 这 ...
随机推荐
- 查看端口被占用并结束进程 mac
- 【Luogu】P2468粟粟的书架(主席树+前缀和)
题目链接 我仿佛中了个爆零debuff 本题分成两部分,五十分用前缀和,f[i][j][k]表示(1,1)到(i,j)的矩形大于等于k的有多少个数(再记录页数和),查询时二分,另外的用主席树,类似方法 ...
- tomcat 启动慢解决(/dev/random)
JRE默认使用 /dev/random作为随机数来源,当熵池大小不够的时候,random会很慢,造成随机数生成调用阻塞. 解决方案: 改用 /dev/urandom (1) tomcat的启动选项增加 ...
- 论文笔记《ImageNet Classification with Deep Convolutional Neural Network》
一.摘要 了解CNN必读的一篇论文,有些东西还是可以了解的. 二.结构 1. Relu的好处: 1.在训练时间上,比tanh和sigmod快,而且BP的时候求导也很容易 2.因为是非饱和函数,所以基本 ...
- 关于python的整形(int)自动转长整形(long)的问题
有时需要访问某个接口,其中传入的整形参数可能比较长就会变成long,这时如果用str()的话‘L’就会被转化到字符串中,导致接口不能识别: 这种情况下应该优先使用json来转译,可以完美保持翻译pyt ...
- LOJ#2131. 「NOI2015」寿司晚宴
$n \leq 500$,$2-n$这些数字,两个人挑,可以重复挑,问有几种方案中,一个人选的所有数字与另一个人选的所有数字都互质. 不像前两题那么抠脚.. 如果$n$比较小的话,可以把两个人选的数字 ...
- 【SQL Server】修改DB逻辑文件名称
步骤一:查询当前DB逻辑文件名称(主逻辑文件.日志逻辑文件) ; 步骤二:步骤二改变(还原)DB逻辑文件名称 RESTORE DATABASE AW831 FROM DISK='D:\AW831.DA ...
- hdu 5952 Counting Cliques 求图中指定大小的团的个数 暴搜
题目链接 题意 给定一个\(n个点,m条边\)的无向图,找出其中大小为\(s\)的完全图个数\((n\leq 100,m\leq 1000,s\leq 10)\). 思路 暴搜. 搜索的时候判断要加进 ...
- duilib入门简明教程 -- XML配置界面(6) (转)
原文转自:http://www.cnblogs.com/Alberl/p/3343699.html 前面那些教程都是为了让小伙伴们从win32.MFC过渡到duilib,让大家觉得duilib ...
- C#byte怎么转成图片
这个其实很简单我给大家提供一个方法吧 /// <summary> /// 字节数组生成图片 /// </summary> /// <param name="By ...