Matrix Power Series

给出矩阵A,求矩阵\(A+A^2+...+A^k\)各个元素\(mod\ yyb\)的值,\(n\leq 30,k\leq 10^9,yyb\leq 10^4\)。

法一:分治

显然是数列题,故数列最浅显的减法是分治,寻找其中重复计算的部分,故可以

\[A+A^2+...+A^{k/2}+A^{k/2+1}+...+A^k=
\]

\[A+A^2+...+A^{k/2}+A^{k/2}(A+...+A^{k/2})+(k\&1)A^k=
\]

\[(A^{k/2}+1)(A+...+A^{k/2})+(k\&1)A^k
\]

对式子主体进行分治,其他的部分快速幂即可。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
using namespace std;
int n,yyb;
struct matrix{
int jz[30][30];
il void clear(){
memset(jz,0,sizeof(jz));
}
il void unit(){
clear();ri int i;
for(i=0;i<n;++i)jz[i][i]|=true;
}
il void read(){
ri int i,j;
for(i=0;i<n;++i)
for(j=0;j<n;++j)
scanf("%d",&jz[i][j]);
}
il void print(){
ri int i,j;
for(i=0;i<n;++i,putchar('\n'))
for(j=0;j<n;++j)
printf("%d ",jz[i][j]);
putchar('\n');
}
il matrix operator*(matrix x){
matrix y;y.clear();ri int i,j,k;
for(i=0;i<n;++i)
for(j=0;j<n;y.jz[i][j]%=yyb,++j)
for(k=0;k<n;++k)
y.jz[i][j]+=jz[i][k]*x.jz[k][j]%yyb;
return y;
}
il matrix operator+(matrix x){
matrix y;ri int i,j;
for(i=0;i<n;++i)
for(j=0;j<n;++j)
y.jz[i][j]=(jz[i][j]+x.jz[i][j])%yyb;
return y;
}template<class free>
il matrix operator^(free y){
matrix x(*this),ans;ans.unit();
while(y){
if(y&1)ans=ans*x;
x=x*x,y>>=1;
}return ans;
}
}state,unit,zero;
il matrix efen(int);
int main(){
int k,i;
scanf("%d%d%d",&n,&k,&yyb);
unit.unit(),state.read();
efen(k).print();
return 0;
}
il matrix efen(int y){
if(!y)return unit;
if(y==1)return state;
return ((state^(y>>1))+unit)*efen(y>>1)
+((y&1)?(state^y):zero);
}

法二:矩阵快速幂

显然数列的题目,经常会存在递推方程,于是矩阵快速幂会在其中大有用武之地,于是设\(f_i=A+A^2+...+A^i\),不难有递推方程\(f_i=f_{i-1}+A^i\),于是我们可以同时转移\(f_i,A^i\),故状态矩阵为

\[\begin{bmatrix}A_i&f_{i-1}\end{bmatrix}
\]

转移矩阵为

\[\begin{bmatrix}A&I\\0&I\end{bmatrix}
\]

以此矩阵中套矩阵仿照套路即可。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
using namespace std;
int n,yyb;
struct matrix1{
int jz[30][30];
il void read(){
ri int i,j;
for(i=0;i<n;++i)
for(j=0;j<n;++j)
scanf("%d",&jz[i][j]);
}
il void print(){
ri int i,j;
for(i=0;i<n;++i,putchar('\n'))
for(j=0;j<n;++j)
printf("%d ",jz[i][j]);
putchar('\n');
}
il void clear(){
memset(jz,0,sizeof(jz));
}
il void unit(){
clear();ri int i;
for(i=0;i<n;++i)jz[i][i]|=true;
}
il matrix1 operator*(matrix1 x){
matrix1 y;y.clear();
ri int i,j,k;
for(i=0;i<n;++i)
for(j=0;j<n;y.jz[i][j]%=yyb,++j)
for(k=0;k<n;++k)
y.jz[i][j]+=jz[i][k]*x.jz[k][j]%yyb;
return y;
}
il matrix1 operator+(matrix1 x){
matrix1 y;ri int i,j;
for(i=0;i<n;++i)
for(j=0;j<n;++j)
y.jz[i][j]=(jz[i][j]+x.jz[i][j])%yyb;
return y;
}template<class free>
il matrix1 operator^(free y){
matrix1 ans,x(*this);ans.unit();
while(y){
if(y&1)ans=ans*x;
x=x*x,y>>=1;
}return ans;
}
}A;
struct matrix2{
matrix1 jz[2][2];
il void clear(){
memset(jz,0,sizeof(jz));
}
il void unit(){
clear();ri int i;
for(i=0;i<2;++i)jz[i][i].unit();
}
il matrix2 operator*(matrix2 x){
matrix2 y;y.clear();
ri int i,j,k;
for(i=0;i<2;++i)
for(j=0;j<2;++j)
for(k=0;k<2;++k)
y.jz[i][j]=y.jz[i][j]+jz[i][k]*x.jz[k][j];
return y;
}template<class free>
il matrix2 operator^(free y){
matrix2 ans,x(*this);ans.unit();
while(y){
if(y&1)ans=ans*x;
x=x*x,y>>=1;
}return ans;
}
}state,tran;
int main(){
int k;
scanf("%d%d%d",&n,&k,&yyb);
A.read(),state.jz[0][0]=A;
tran.jz[0][0]=A,tran.jz[0][1].unit();
tran.jz[1][1].unit(),state=state*(tran^k);
state.jz[0][1].print();
return 0;
}

法三:倍增前缀和优化

数列求和可以利用倍增优化,主要思想是维护\(A^{2^i}\),这个显然可通过\(A^{2^{i+1}}=(A^{2^i})^2\)来暴力递推,再维护一个倍增的数列,\(f_i=A^1+A^2+...+A^{2^i}\),不难得知其转移方程为\(f_i=f_{i-1}A^{2^{i-1}}+f_{i-1}\),而这个的维护也可以暴力维护,于是对于我们的求和,以\(A+A^2+...+A^{15}\)为例,有

\[A+A^2+...+A^{15}=f_3+A^9+...+A^{15}=
\]

\[f_3+A^8(A+...+A^7)=f_3+A^8(f_2+A^5+A^6+A^7)=
\]

\[f_3+A^8[f_2+A^4(A+A^2+A^3)]=
\]

\[f_3+A^8[f_2+A^4(f_1+A^2A^1)]=f_3+A^8[f_2+A^4(f_1+A^2f_0)]
\]

于是按照这个先维护好一段倍增前缀和,再对后式提公因式,继续利用倍增前缀和优化,不停地继续,即可得到答案,当然你也可以递归处理,以下参考程序用的是非递归的方式。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
using namespace std;
int n,yyb;
struct matrix{
int jz[30][30];
il void clear(){
memset(jz,0,sizeof(jz));
}
il void unit(){
clear();ri int i;
for(i=0;i<n;++i)jz[i][i]|=true;
}
il void read(){
ri int i,j;
for(i=0;i<n;++i)
for(j=0;j<n;++j)
scanf("%d",&jz[i][j]);
}
il void print(){
ri int i,j;
for(i=0;i<n;putchar('\n'),++i)
for(j=0;j<n;++j)
printf("%d ",jz[i][j]);
putchar('\n');
}
il matrix operator*(matrix x){
matrix y;ri int i,j,k;y.clear();
for(i=0;i<n;++i)
for(j=0;j<n;y.jz[i][j]%=yyb,++j)
for(k=0;k<n;++k)
y.jz[i][j]+=jz[i][k]*x.jz[k][j]%yyb;
return y;
}
il matrix operator+(matrix x){
matrix y;ri int i,j;
for(i=0;i<n;++i)
for(j=0;j<n;++j)
y.jz[i][j]=(jz[i][j]+x.jz[i][j])%yyb;
return y;
}
}A,p[31],sum[31],ans,jilu;
int main(){
int k,i;
scanf("%d%d%d",&n,&k,&yyb);
A.read(),p[0]=A,jilu.unit(),sum[0]=A;
for(i=1;i<=30;++i)p[i]=p[i-1]*p[i-1];
for(i=1;i<=30;++i)sum[i]=sum[i-1]*p[i-1]+sum[i-1];
for(i=30;i>=0;--i)
if(k>>i&1){
ans=ans+sum[i]*jilu;
jilu=jilu*p[i];
}ans.print();
return 0;
}

总上所诉,不难得知数列题目的一般求法,矩阵快速幂和分治,而特殊地对于数列前缀和的问题,我们可以利用倍增前缀和优化,但无论如何,数列问题绝不只一条道路通往罗马。

Matrix Power Series的更多相关文章

  1. 线性代数(矩阵乘法):POJ 3233 Matrix Power Series

    Matrix Power Series   Description Given a n × n matrix A and a positive integer k, find the sum S = ...

  2. C++题解:Matrix Power Series ——矩阵套矩阵的矩阵加速

    Matrix Power Series r时间限制: 1 Sec 内存限制: 512 MB 题目描述 给定矩阵A,求矩阵S=A^1+A^2+--+A^k,输出矩阵,S矩阵中每个元都要模m. 数据范围: ...

  3. POJ 3233 Matrix Power Series(二分等比求和)

    Matrix Power Series [题目链接]Matrix Power Series [题目类型]二分等比求和 &题解: 这题我原来用vector写的,总是超时,不知道为什么,之后就改用 ...

  4. POJ 3233 Matrix Power Series (矩阵乘法)

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

  5. 构造矩阵解决这个问题 【nyoj299 Matrix Power Series】

    矩阵的又一个新使用方法,构造矩阵进行高速幂. 比方拿 nyoj299 Matrix Power Series 来说 给出这样一个递推式: S = A + A2 + A3 + - + Ak. 让你求s. ...

  6. POJ 3233 Matrix Power Series(矩阵快速幂)

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

  7. POJ 3233 Matrix Power Series 【经典矩阵快速幂+二分】

    任意门:http://poj.org/problem?id=3233 Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K To ...

  8. [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:  ...

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

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

  10. [POJ3233]Matrix Power Series 分治+矩阵

    本文为博主原创文章,欢迎转载,请注明出处 www.cnblogs.com/yangyaojia [POJ3233]Matrix Power Series 分治+矩阵 题目大意 A为n×n(n<= ...

随机推荐

  1. org.mybatis总是认不出来的原因,pom.xml中有

    idea打开maven project,然后就华丽丽的看见下载失败,怎么刷新都没有用. 请按以下步骤完成即可: https://blog.csdn.net/ZhengYanFeng1989/artic ...

  2. [转]设置修改CentOS系统时区

    在我们使用CentOS系统的时候,也许时区经常会出现问题,有时候改完之后还是会出错,下面我们就来学习一种方法来改变这个状况.如果没有安装,而你使用的是 CentOS系统 那使用命令 yum insta ...

  3. hexo中加入点击出现小红心的特效会导致无法双击选中和连续点击三次选中一整行的操作

    文章目录 问题描述 解决 个人博客:https://mmmmmm.me 源码:https://github.com/dataiyangu/dataiyangu.github.io 问题描述 如题,我们 ...

  4. TCP/IP点滴

    1 子网的划分 2 子网的表述 ipv4 IPv4中规定IP地址长度为32,最大地址个数为2^32,点分十进制表示方法:122.70.156.25. ipv6 地址的长度为128,即最大地址个数为2^ ...

  5. Codeforces 1154B Make Them Equal

    题目链接:http://codeforces.com/problemset/problem/1154/B 题意:给定数组,可以给任意的的元素加上D 或者 减去D,如果能 使数组元素都相等,输出最小的D ...

  6. 网页重构应该避免的10大CSS糟糕用法

    对于网页重构来说,CSS禅意花园 是网页布局从 table 表格转到了 html +css 的标志 .这些年来,随着我们的网站越来越复杂:html5,css3,新的技术.新的属性,越来越多的开发者开始 ...

  7. 解决:Map的area属性标签鼠标Hover可以给area加背景

    css的area标签是不支持hover的,只有a标签才支持.li标签在IE浏览器下才支持,所以采用jquery的mouseenter和mouseleave事件完成.首先讲jQuery对应的事件:1.m ...

  8. jQuery Ajax请求 .net 一般处理程序

    初学ajax 一个简单的功能,调试了2个小时,代码如下虽然成功了 但是有错误 <!DOCTYPE html> <html> <head> <meta http ...

  9. DRF的视图组件

    目录 DRF的视图组件 两大视图类 六大视图工具类 九大工具视图类 两大视图集基类 DRF的视图组件 DRF的视图组件大概分以下几类 两大视图类 APIView.GenericAPIView from ...

  10. <mysql>mysql基础学习

    1.Join语法 JOIN 按照功能大致分为如下三类: INNER JOIN(内连接,或等值连接):取得两个表中存在连接匹配关系的记录. LEFT JOIN(左连接):取得左表(table1)完全记录 ...