题目:Matrix Power Series

传送门:http://poj.org/problem?id=3233

分析:

方法一:引用Matrix67大佬的矩阵十题:这道题两次二分,相当经典。首先我们知道,A^i可以二分求出。然后我们需要对整个题目的数据规模k进行二分。比如,当k=6时,有:$ S(6)= A + A^2 + A^3 + A^4 + A^5 + A^6 =\underline{(A + A^2 + A^3)} + A^3*\underline{(A + A^2 + A^3)}。   $

即对于k:如果k是偶数,就二分减小规模,$ S(k)=S(\frac{k}{2})+A^{\frac{n}{2}} *S(\frac{k}{2}) $。如果k是奇数,那么 $ S(k)=S(k-1)+A^n $; 其中 $ A^n $使用矩阵快速幂可以快速计算。

 #include <iostream>
#include <cstdio>
using namespace std;
const int maxN=;
int MOD;
struct Matrix{int n,a[maxN][maxN];}A,E;
Matrix operator+(Matrix A,Matrix B){
Matrix RT{};RT.n=A.n;
for(int i=;i<RT.n;++i)
for(int j=;j<RT.n;++j)
RT.a[i][j]=(A.a[i][j]+B.a[i][j])%MOD;
return RT;
}
Matrix operator*(Matrix A,Matrix B){
Matrix RT{};RT.n=A.n;
for(int i=;i<A.n;++i)
for(int j=;j<A.n;++j)
for(int k=;k<A.n;++k)
(RT.a[i][j]+=A.a[i][k]*B.a[k][j])%=MOD;
return RT;
}
Matrix operator^(Matrix A,int n){
Matrix RT=E;
for(;n;n>>=){
if(n&)RT=RT*A;
A=A*A;
}
return RT;
}
Matrix Sum(Matrix &A,int n){
if(n==)return A;
if(n&)return (A^n) + Sum(A,n-);
Matrix B=Sum(A,n>>);
return B+((A^(n>>))*B);
}
int main(){
for(int n,k;~scanf("%d %d %d",&n,&k,&MOD);){
A.n=E.n=n;
for(int i=;i<n;++i)
for(int j=;j<n;++j){
scanf("%d",&A.a[i][j]);
A.a[i][j]%=MOD;E.a[i][j]=;
}
for(int i=;i<n;++i)E.a[i][i]=;
Matrix RT=Sum(A,k);
for(int i=;i<n;++i){
for(int j=;j<n;++j)
printf("%d ",RT.a[i][j]);
puts("");
}
}
return ;
}

方法二:对于多项式,有秦九韶算法,而对$ A + A^2 + A^3 + … + A^k $ 这样的多项式,可以二进制优化秦九韶算法。$ S( 2^i ) $ 是可以快速计算的: $S( 2^i ) = S( 2^{(i-1)} ) * (E + A^{(2^i)} )$。记:$A[i]=A^{2^i}$、$S[i]=S(2^i)$;预处理A[i]、s[i]。

比如k=6时:$ S(6)=\underline{(A + A^2 + A^3 + A^ 4)} * A^2 + \underline{(A + A^2 )} = S(4) * A(2) + S(2) = S[2]*A[1]+S[1] $

 #include <iostream>
#include <cstdio>
using namespace std;
const int maxN=;
int MOD;
struct Matrix{int n,a[maxN][maxN];}A[],B[];
Matrix operator+(Matrix A,Matrix B){
Matrix RT{};RT.n=A.n;
for(int i=;i<RT.n;++i)
for(int j=;j<RT.n;++j)
RT.a[i][j]=(A.a[i][j]+B.a[i][j])%MOD;
return RT;
}
Matrix operator*(Matrix A,Matrix B){
Matrix RT{};RT.n=A.n;
for(int i=;i<A.n;++i)
for(int j=;j<A.n;++j)
for(int k=;k<A.n;++k)
(RT.a[i][j]+=A.a[i][k]*B.a[k][j])%=MOD;
return RT;
}
int main(){
Matrix E{};
for(int n,k;~scanf("%d %d %d",&n,&k,&MOD);){
A[].n=E.n=n;
for(int i=;i<n;++i)
for(int j=;j<n;++j){
scanf("%d",&A[].a[i][j]);
A[].a[i][j]%=MOD;E.a[i][j]=;
}
for(int i=;i<n;++i)E.a[i][i]=;
for(int i=;k>>i;++i)A[i]=A[i-]*A[i-];
B[]=A[];
for(int i=;k>>i;++i)B[i]=B[i-]*(A[i-]+E);
Matrix RT{};RT.n=n;
for(int i=;~i;--i)if(k>>i&)RT=RT*A[i]+B[i];
for(int i=;i<n;++i){
for(int j=;j<n;++j)
printf("%d ",RT.a[i][j]);
puts("");
}
}
return ;
}

优化一下常数(141s -> 32s):

 #include <iostream>
#include <cstdio>
using namespace std;
const int maxN=;
int MOD;
struct Matrix{int n,a[maxN][maxN];}A[],B[];
Matrix operator+(Matrix A,Matrix B){
Matrix RT{};RT.n=A.n;
for(int i=;i<RT.n;++i)
for(int j=;j<RT.n;++j){
RT.a[i][j]=A.a[i][j]+B.a[i][j];
if(RT.a[i][j]>=MOD)RT.a[i][j]-=MOD;
}
return RT;
}
Matrix operator*(Matrix A,Matrix B){
Matrix RT{};RT.n=A.n;
for(int i=;i<A.n;++i)
for(int j=;j<A.n;++j){
for(int k=;k<A.n;++k)
RT.a[i][j]+=A.a[i][k]*B.a[k][j];
RT.a[i][j]%=MOD;
}
return RT;
}
int main(){
Matrix E{};
for(int n,k;~scanf("%d %d %d",&n,&k,&MOD);){
A[].n=E.n=n;
for(int i=;i<n;++i)
for(int j=;j<n;++j){
scanf("%d",&A[].a[i][j]);
A[].a[i][j]%=MOD;E.a[i][j]=;
}
for(int i=;i<n;++i)E.a[i][i]=;
for(int i=;k>>i;++i)A[i]=A[i-]*A[i-];
B[]=A[];
for(int i=;k>>i;++i)B[i]=B[i-]*(A[i-]+E);
Matrix RT{};RT.n=n;
for(int i=;~i;--i)if(k>>i&)RT=RT*A[i]+B[i];
for(int i=;i<n;++i){
for(int j=;j<n;++j)
printf("%d ",RT.a[i][j]);
puts("");
}
}
return ;
}

方法三:有种很有意思的打法:构造矩阵

$ T = \left[ \begin{array}{cc} E & 0 \\ A & A \end{array}  \right]$ 、 $ T^2 =  \left[ \begin{array}{cc} E & 0 \\ {A + A^2}  & A^2 \end{array}  \right]$ 、 $ T^2 =  \left[ \begin{array}{cc} E & 0 \\ {A + A^2 + A^3}  & A^3 \end{array} \right]$ 、

这个矩阵的左下角就是矩阵次方和。$ T^n =  \left[ \begin{array}{cc} E & 0 \\ {A + A^2 + .. A^n}  & A^n \end{array} \right]$

这个矩阵可以直接快速幂求。

把RT矩阵设为 $ RT =  \left[ \begin{array}{cc} 0 & E \\ 0  & 0 \end{array} \right] $,然后 $ RT \times T^n =   \left[ \begin{array}{cc} {A + A^2 + .. A^n} & 0 \\ 0  & 0 \end{array} \right] $

 #include <iostream>
#include <cstdio>
using namespace std;
const int maxN=;
int MOD;
struct Matrix{int n,a[maxN][maxN];}A;
Matrix operator+(Matrix A,Matrix B){
Matrix RT{};RT.n=A.n;
for(int i=;i<RT.n;++i)
for(int j=;j<RT.n;++j){
RT.a[i][j]=A.a[i][j]+B.a[i][j];
if(RT.a[i][j]>=MOD)RT.a[i][j]-=MOD;
}
return RT;
}
Matrix operator*(Matrix A,Matrix B){
Matrix RT{};RT.n=A.n;
for(int i=;i<A.n;++i)
for(int j=;j<A.n;++j){
for(int k=;k<A.n;++k)
RT.a[i][j]+=A.a[i][k]*B.a[k][j];
RT.a[i][j]%=MOD;
}
return RT;
}
Matrix Sum(Matrix A,int k){
Matrix RT{};int n=RT.n=A.n;
for(int t=n/,i=;i<n;++i)RT.a[i][i+t]=;
for(;k;k>>=){
if(k&)RT=RT*A;
A=A*A;
}
return RT;
}
int main(){
for(int n,k;~scanf("%d %d %d",&n,&k,&MOD);){
A.n=n<<;
for(int i=;i<n;++i){
A.a[i][i]=;
for(int j=,t;j<n;++j){
scanf("%d",&t);if(t>=MOD)t%=MOD;
A.a[i+n][j]=A.a[i+n][j+n]=t;
}
}
Matrix RT=Sum(A,k);
for(int i=;i<n;++i){
for(int j=;j<n;++j)
printf("%d ",RT.a[i][j]);
puts("");
}
}
return ;
}

题目: Gauss Fibonacci

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1588

分析:Fibonacci数列可用矩阵:$ Fib =  \left[ \begin{array}{cc} 0 & 1 \\ 1  & 1 \end{array} \right] $ 表示,f(i)=$Fib^n$的左下角元素的值。

然后即求 $ Fib^b + Fib^{k+b} + Fib^{2*k+b} + ... Fib^{(n-1)*k+b} $

即:$ Fib^b * (E + Fib^k + Fib^{2*k} + Fib^{3*k} + ... +Fib^{(n-1)*k} $ = $ Fib^b * (E + (Fib^k) + {(Fib^k)}^2 + {(Fib^k)}^3 + ... +{(Fib^k)}^{(n-1)} )$

令  $ A=Fib^k $;

则求: $ Fib^b * (E + A + A^2 + A^3 +.. A^n) $

就和上面一样了。

 #include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
const int maxN=;
LL MOD;
struct Matrix{LL a[maxN][maxN];}A[],B[],E,Fib;
Matrix operator+(Matrix A,Matrix B){
Matrix RT{};
for(int i=;i<;++i)
for(int j=;j<;++j){
RT.a[i][j]=A.a[i][j]+B.a[i][j];
if(RT.a[i][j]>=MOD)RT.a[i][j]-=MOD;
}
return RT;
}
Matrix operator*(Matrix A,Matrix B){
Matrix RT{};
for(int i=;i<;++i)
for(int j=;j<;++j){
for(int k=;k<;++k)
RT.a[i][j]+=A.a[i][k]*B.a[k][j];
RT.a[i][j]%=MOD;
}
return RT;
}
Matrix operator^(Matrix A,LL n){
Matrix RT=E;
for(;n;n>>=){
if(n&)RT=RT*A;
A=A*A;
}
return RT;
}
int main(){
for(LL k,b,n;~scanf("%lld %lld %lld %lld",&k,&b,&n,&MOD);){
--n;
Fib.a[][]=;Fib.a[][]=;
Fib.a[][]=;Fib.a[][]=;
E.a[][]=E.a[][]=;
E.a[][]=E.a[][]=; A[]=Fib^k;
for(int i=;n>>i;++i)A[i]=A[i-]*A[i-];
B[]=A[];
for(int i=;n>>i;++i)B[i]=B[i-]*(A[i-]+E); Matrix RT{};
for(int i=;~i;--i)if(n>>i&)RT=RT*A[i]+B[i];
RT=(RT+E)*(Fib^b);
printf("%lld\n",RT.a[][]);
}
return ;
}
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
const int maxN=;
LL MOD;
struct Matrix{int n;LL a[maxN][maxN];}A,Fib;
Matrix operator+(Matrix A,Matrix B){
Matrix RT{};
for(int i=;i<;++i)
for(int j=;j<;++j){
RT.a[i][j]=A.a[i][j]+B.a[i][j];
if(RT.a[i][j]>=MOD)RT.a[i][j]-=MOD;
}
return RT;
}
Matrix operator*(Matrix A,Matrix B){
Matrix RT{};int n=RT.n=A.n;
for(int i=;i<n;++i)
for(int j=;j<n;++j){
for(int k=;k<n;++k)
RT.a[i][j]+=A.a[i][k]*B.a[k][j];
RT.a[i][j]%=MOD;
}
return RT;
}
Matrix operator^(Matrix A,LL n){
Matrix RT;
RT.n=A.n;
for(int i=;i<RT.n;++i)for(int j=;j<RT.n;++j)RT.a[i][j]=;
for(int i=;i<RT.n;++i)RT.a[i][i]=;
for(;n;n>>=){
if(n&)RT=RT*A;
A=A*A;
}
return RT;
}
int main(){
for(LL k,b,n;~scanf("%lld %lld %lld %lld",&k,&b,&n,&MOD);){
--n;
Fib.n=;
Fib.a[][]=;Fib.a[][]=;
Fib.a[][]=;Fib.a[][]=; A=Fib^k;
A.n=;
A.a[][]=A.a[][]=A.a[][];
A.a[][]=A.a[][]=A.a[][];
A.a[][]=A.a[][]=A.a[][];
A.a[][]=A.a[][]=A.a[][];
A.a[][]=;A.a[][]=;
A.a[][]=;A.a[][]=; A=A^n;
A.n=;
A.a[][]=A.a[][]+;A.a[][]=A.a[][]+;
A.a[][]=A.a[][]+;A.a[][]=A.a[][]+; A=(Fib^b)*A;
printf("%lld\n",A.a[][]);
}
return ;
}

POJ3233]Matrix Power Series && [HDU1588]Gauss Fibonacci的更多相关文章

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

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

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

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

  3. POJ3233 Matrix Power Series

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

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

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

  5. POJ3233 Matrix Power Series(矩阵快速幂+分治)

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

  6. POJ3233:Matrix Power Series(矩阵快速幂+递推式)

    传送门 题意 给出n,m,k,求 \[\sum_{i=1}^kA^i\] A是矩阵 分析 我们首先会想到等比公式,然后得到这样一个式子: \[\frac{A^{k+1}-E}{A-E}\] 发现要用矩 ...

  7. POJ-3233 Matrix Power Series 矩阵A^1+A^2+A^3...求和转化

    S(k)=A^1+A^2...+A^k. 保利求解就超时了,我们考虑一下当k为偶数的情况,A^1+A^2+A^3+A^4...+A^k,取其中前一半A^1+A^2...A^k/2,后一半提取公共矩阵A ...

  8. POJ3233 Matrix Power Series(快速幂求等比矩阵和)

    题面 \(solution:\) 首先,如果题目只要我们求\(A^K\) 那这一题我们可以直接模版矩乘快速幂来做,但是它现在让我们求$\sum_{i=1}^{k}{(A^i)} $ 所以我们思考一下这 ...

  9. poj3233 Matrix Power Series(矩阵快速幂)

    题目要求的是 A+A2+...+Ak,而不是单个矩阵的幂. 那么可以构造一个分块的辅助矩阵 S,其中 A 为原矩阵,E 为单位矩阵,O 为0矩阵    将 S 取幂,会发现一个特性: Sk +1右上角 ...

随机推荐

  1. Delphi IdHttp组件+IdHttpServer组件实现文件下载服务

     http://blog.csdn.net/xxkku521/article/details/16864759 Delphi IdHttp组件+IdHttpServer组件实现文件下载服务 2013- ...

  2. poj3126Prime Path (BFS+素数筛)

    素数筛:需要一个数组进行标记 最小的素数2,所有是2的倍数的数都是合数,对合数进行标记,然后找大于2的第一个非标记的数(肯定是素数),将其倍数进行标记,如此反复,若是找n以内的所有素数,只需要对[2, ...

  3. [LeetCode] 421. Maximum XOR of Two Numbers in an Array(位操作)

    传送门 Description Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231. Fin ...

  4. apt-get updete以及apt-get upgrade的区别

    You should first run update, then upgrade. Neither of them automatically runs the other. apt-get upd ...

  5. Entity Framework 中遇到的一些小问题

    一.在多表关联中,一个表中有另一个表的model累,在Include方法里提示lambda表达式不是委托类型,这时候需要using System.Data.Entity; 二.插入数据时,主键并非自增 ...

  6. swagger2文档使用

    ①.导入依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-sw ...

  7. [转]云计算:SaaS、PaaS、IaaS、CaaS

    http://blog.csdn.net/it_man/article/details/8441902 近两年来,随着云计算技术的飞速发展,越来越多的厂商意识到了它巨大的潜在价值.随着微软.IBM.G ...

  8. C#面试 笔试题 四

    1.请你简单的说明数据库建立索引的优缺点 使用索引可以加快数据的查询速度,不过由于数据插入过程中会建索引,所以会降低数据的插入.更新速度,索引还会占磁盘空间. 2.什么是WEB服务控件?使用WEB服务 ...

  9. centos7配置sudo免密

    1.chmod  +w   /etc/sudoers 2.vim  /etc/sudoers 在已经有了的root下面加 username  ALL=NOPASSWD:ALL      (这是所有的命 ...

  10. 快速部署业务类为webapi服务

    接着前一篇博文,将接口快速打包固定请求格式,不需要修改代码,可以自动完成接口调用,实际上就是生成了一个接口的代理类. 那么仅仅是接口请求代理,没有服务端怎么行?所以需要将实现接口的类部署为webapi ...