POJ 3233 Matrix Power Series——快速幂&&等比&&分治
题目
给定一个 $n \times n$ 的矩阵 $A$ 和正整数 $k$ 和 $m$。求矩阵 $A$ 的幂的和。
$$S = A + A^2 + ... + A^k$$
输出 $S$ 的各个元素对 $M$ 取余后的结果($1 \leq n \leq 30, 1 \leq k \leq 10^9, 1 \leq M \leq 10^4$)。
分析
数据范围 $n$ 很小,$k$ 很大,不肯能逐一求得。
由于具有等比性质,
设 $S_k = I + A + ... + A^{k-1}$
则有
$$\begin{pmatrix} A^k\\ S_k \end{pmatrix} = \begin{pmatrix} A & 0\\ I & I \end{pmatrix} \begin{pmatrix} A^{k-1}\\ S_{k-1} \end{pmatrix} = \begin{pmatrix} A & 0\\ I & I \end{pmatrix}^k\begin{pmatrix} I\\ 0 \end{pmatrix}$$
对这个新矩阵使用快速幂即可。
代码中的输出,使用了分块矩阵乘法的性质进行了简化。
#include<cstdio>
#include<cstring>
using namespace std; typedef long long ll;
struct matrix
{
int r, c;
int mat[][];
matrix(){
memset(mat, , sizeof(mat));
}
};
int n, k, p; matrix mul(matrix A, matrix B) //矩阵相乘
{
matrix ret;
ret.r = A.r; ret.c = B.c;
for(int i = ;i < A.r;i++)
for(int k = ;k < A.c;k++)
for(int j = ;j < B.c;j++)
{
ret.mat[i][j] = (ret.mat[i][j] + A.mat[i][k] * B.mat[k][j]) % p;
}
return ret;
} matrix mpow(matrix A, int n)
{
matrix ret;
ret.r = A.r; ret.c = A.c;
for(int i = ;i < ret.r;i++) ret.mat[i][i] = ;
while(n)
{
if(n & ) ret = mul(ret, A);
A = mul(A, A);
n >>= ;
}
return ret;
} int main()
{
scanf("%d%d%d", &n, &k, &p);
matrix a, b;
a.r = a.c = n;
for(int i = ;i < n;i++) for(int j = ;j < n;j++) scanf("%d", &a.mat[i][j]);
b.r = b.c = *n;
for(int i = ;i < n;i++)
{
for(int j = ;j < n;j++) b.mat[i][j] = a.mat[i][j];
b.mat[n+i][i] = b.mat[n+i][n+i] = ;
}
b = mpow(b, k+);
for(int i = ;i < n;i++)
for(int j = ;j < n;j++)
{
int tmp = b.mat[n+i][j] % p;
if(i == j) tmp = (tmp + p - ) % p;
printf("%d%c", tmp, j == n- ? '\n' : ' ');
}
}
还有一种经典的分治方法,
例如,
$A+A^2+A^3+A^4 = (A+A^2) + A^2(A + A^2)$,
$A+A^2+A^3+A^4+A^5 = (A+A^2) +A^3 + A^3(A + A^2)$.
因此,分k的奇偶递归一下就可以了。
#include<cstdio>
#include<cstring>
using namespace std; typedef long long ll;
struct matrix
{
int r, c;
int mat[][];
matrix(){
memset(mat, , sizeof(mat));
}
};
int n, k, p; matrix mul(matrix A, matrix B) //矩阵相乘
{
matrix ret;
ret.r = A.r; ret.c = B.c;
for(int i = ;i < A.r;i++)
for(int k = ;k < A.c;k++)
for(int j = ;j < B.c;j++)
{
ret.mat[i][j] = (ret.mat[i][j] + A.mat[i][k] * B.mat[k][j]) % p;
}
return ret;
} matrix mpow(matrix A, int n)
{
matrix ret;
ret.r = A.r; ret.c = A.c;
for(int i = ;i < ret.r;i++) ret.mat[i][i] = ;
while(n)
{
if(n & ) ret = mul(ret, A);
A = mul(A, A);
n >>= ;
}
return ret;
} matrix add(matrix A, matrix B)
{
matrix ret;
ret.r = A.r; ret.c = A.c;
for(int i = ;i < A.r;i++)
for(int j = ;j < A.c;j++)
ret.mat[i][j] = (A.mat[i][j] + B.mat[i][j]) % p;
return ret;
} matrix sum(matrix x, int k) //A+A^2+..+A^k
{
if(k == ) return x;
matrix s = sum(x, k/);
if(k & )
{
matrix tmp = mpow(x, k/+);
return add(s, add(tmp, mul(tmp, s)));
}
else
{
matrix tmp = mpow(x, k/);
return add(s, mul(tmp, s));
}
} int main()
{
scanf("%d%d%d", &n, &k, &p);
matrix a, ans;
a.r = a.c = n;
for(int i = ;i < n;i++) for(int j = ;j < n;j++) scanf("%d", &a.mat[i][j]);
ans = sum(a, k);
for(int i = ;i < n;i++) for(int j = ;j < n;j++) printf("%d%c", ans.mat[i][j], j == n- ? '\n' : ' ');
}
这个时间复杂度咋算啊?知道的大犇请留言。
参考链接:
1. https://blog.csdn.net/rowanhaoa/article/details/21023599
2. https://blog.csdn.net/scf0920/article/details/39345197
POJ 3233 Matrix Power Series——快速幂&&等比&&分治的更多相关文章
- 矩阵十点【两】 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: 19338 Accepted: 8161 ...
- 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: 11954 Accepted: ...
- [ACM] POJ 3233 Matrix Power Series (求矩阵A+A^2+A^3...+A^k,二分求和或者矩阵转化)
Matrix Power Series Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 15417 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 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写的,总是超时,不知道为什么,之后就改用 ...
随机推荐
- 解决计算精度问题:BigDecimal
BigDecimal类 BigDecimal所在包:java.math,不可变的.任意精度的有符号十进制数.BigDecimal 由任意精度的整数非标度值 和 32 位的整数标度 (scale) 组成 ...
- Python小知识点+保留字
注意 !/usr/bin/python # -- coding: UTF-8 -- #中文编码 Python空行:函数之间或类的方法之间用空行分隔,表示一段新的代码的开始 Python注释:单行注释采 ...
- kubernetes 实践一:基本概念和架构
这里记录kubernetes学习和使用过程中的内容. CentOS7 k8s-1.13 flanneld-0.10 docker-18.06 etcd-3.3 kubernetes基本概念 kuber ...
- JDK提供的原子类和AbstractQueuedSynchronizer(AQS)
大致分成: 1.原子更新基本类型 2.原子更新数组 3.原子更新抽象类型 4.原子更新字段 import java.util.concurrent.atomic.AtomicInteger; impo ...
- GRE
第一个技术是GRE,全称Generic Routing Encapsulation,它是一种IP-over-IP的隧道技术.它将IP包封装在GRE包里,外面加上IP头,在隧道的一端封装数据包,并在通路 ...
- 北航OO课程完结总结
什么是OO? 面向对象,是一种编程的思想方法,但是在这门课程中,我们实际学习到的是将理论运用到具体实践上,将自己的想法付诸实践,不断去探索和优化的这一体验. 后两次作业架构总结 本单元两次作业,我们面 ...
- rabbitMq 学习笔记(二) 备份交换器,过期时间,死信队列,死信队列
备份交换器 备份交换器,英文名称为 Altemate Exchange,简称庙,或者更直白地称之为"备胎交换器". 生产者在发送消息的时候如果不设置 mandatory 参数, 那 ...
- 【开发工具】- Xshell工具的下载和安装
下载地址:https://www.netsarang.com/zh/free-for-home-school/ Xshell 是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Micro ...
- mySql入门-(二)
最近刚刚开始学习Mysql,然而学习MySql必经的一个过程就是SQL语句,只有按照文档从头开始学习SQL语句.学习的过程是痛苦的,但是学完的成果是甘甜的. SQL 语法 所有的 SQL 语句都以下列 ...
- ElementUI 源码定制防坑指南
背景 我司OA系统公文管理模块Office在线编辑使用的是金格IWebOffice中间件[PPAPI插件,通过<object>标签加载],IWebOffice在chrome中设置div盒子 ...