poj 3233 Matrix Power Series

7 篇文章 0 订阅
6 篇文章 0 订阅

H - Matrix Power Series

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

 

 

题意:已知一个n*n的矩阵A,和一个正整数k,求S = A + A2 + A3 + + Ak

 

思路:矩阵快速幂。首先我们知道 A^x 可以用矩阵快速幂求出来(具体可见poj 3070)。其次可以对k进行二分,每次将规模减半,分k为奇偶两种情况,如当k = 6k = 7时有:

      k = 10 有: S(10) = ( A^1+A^2+A^3+A^4+ A^5 ) + A^5 * ( A^1+A^2+A^3+A^4+A^5 ) = S(5) + A^5 * S(5)

      k = 5 有: S(5) = ( A^1+A^2 ) + A^3 + A^3 * ( A^1+A^2 ) = S(2) + A^3 + A^3 * S(2)

  k = 2 :  S(2) = A^1 + A^2 = S(1) + A^1 * S(1)

 

二分 递归 矩阵 快速幂

 

#include <cstdio>

#include <cstring>

using namespace std ;

struct node

{

    int a[50][50] ;

};

int n,k,m;

node mul(node p,node q)//矩阵乘法

{

    node s;

    int i,j,k;

    for(i=0;i<n;i++)

    {

        for(j=0;j<n;j++)

        {

            s.a[i][j]=0 ;

            for(k=0;k<n;k++)

            {

                s.a[i][j]=(s.a[i][j]+p.a[i][k]*q.a[k][j])%m;

            }

        }

    }

    return s ;

}

node add(node p,node q)//矩阵加法

{

    int i,j;

    node s;

    for(i=0;i<n;i++)

        for(j=0;j<n;j++)

            s.a[i][j]=(p.a[i][j]+q.a[i][j])%m ;

    return s ;

}

node pow(node p,int k)//矩阵快速幂

{

    if(k==1)

        return p;

    node s=pow(p,k/2);

    s=mul(s,s);

    if(k%2)

        s=mul(s,p);

    return s;

}

node f(node p,int k)//二分递归

{

    if(k==1)

        return p;

    node s=f(p,k/2),q,temp;

    int i,j;

    for(i=0;i<n;i++)

    {

        for(j=0;j<n;j++)

        {

            if(i==j)

                temp.a[i][j]=1;

            else

                temp.a[i][j]=0;

        }

    }标准矩阵*任何矩阵都为1

    if(k%2)//奇数

    {

        q=pow(p,k/2+1) ;

        s=add(q,mul(s,add(q,temp))) ;

    }

    else

    {

        q=pow(p,k/2);

        s=mul(s,add(q,temp));

    }

    return s ;

}

int main()

{

    int i,j;

    node p,s;

    while(scanf("%d%d%d",&n,&k,&m)!=EOF)

    {

        for(i=0;i<n;i++)

            for(j=0;j<n;j++)

                scanf("%d",&p.a[i][j]);

        s=f(p,k);

        for(i=0;i<n;i++)

        {

            for(j=0;j<n;j++)

            {

                if(j==n-1)

                    printf("%d\n",s.a[i][j]);

                else

                    printf("%d ",s.a[i][j]);

            }

        }

    }

    return 0;

}

 

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值