题目: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. ElasticSearch删除索引

    curl -X DELETE http://{ES IP address}:9200/{index_name}

  2. python web自动化测试框架搭建(功能&接口)——功能测试模块

    功能测试使用selenium,模块有: 1.futil: 公共方法,如元素高亮显示 # coding=utf-8 """高亮显示元素""" ...

  3. Drone 中的概念:webhooks、workspace、cloning、pipelines、services、plugins、deployments

    webhooks 跳过提交 包含/跳过分支 branches workspace base 属性 path 属性 cloning pipelines 构建步骤 并行执行 group 条件执行 when ...

  4. MySQL 查询语句--------------进阶5:分组查询

    #进阶5:分组查询 /* select 分组函数,列(要求出现在group by的后面) from 表 [where 筛选条件] group by 分组的列表 [order by 子句] 注意: 查询 ...

  5. python操作mysql之增删改查

    [insert] import MySQLdb conn = MySQLdb.connect(","08day5" ) cur = conn.cursor() #把数据放 ...

  6. idea2019.1 永久破解 亲测可用

    idea2019突然注册码突然失效了,搜了很多破解办法,这个还是有效的:https://www.jianshu.com/p/b6dd43618a66

  7. ExcelVBA 操作putty

    Private Sub login(ip As String, userName As String, password As String) Dim TaskID As Long '设置进程id p ...

  8. Erueka异常

    /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | ...

  9. NGUI的widget的使用

    一,我们看看widget有什么属性,如下图: 二,Pivot是什么意思? 我们都知道在Untiy3D中有一个中央坐标点,而这个Pivot这个就是选择控件的某一个点与中央坐标点定位. 如下图区别: 当你 ...

  10. 安装weblogic界面安装

    如果中间有任何问题请联系作者:291562721 界面安装weblogic首先 需要工具: 链接:https://pan.baidu.com/s/1x3uYxsnycjT2Xi2TOTbDdQ 提取码 ...