POJ3233 Matrix Power Series 矩阵乘法

 

这道题目是第三种矩阵乘法的应用。
然我们求 S = A + A 2 + A 3 + … + Ak.的结果矩阵
M67大牛的博客上面讲的是一种分治的方法。
设f[n]=A^1+A^2+....A^n;
当n是偶数,f[n]=f[n/2]+f[n/2]*A^(n/2);
但n是奇数,f[n]=f[n-1]+A^(n);
而看了DISCUSS之后发现一种编程复杂度更加小的方法。再次涨了姿势。。

Let B=[ [A I];
             [0 I] ]

B^(k+1) = [ [A^k   I+A+...+A^k];
                   [0                I        ] ]

只能说矩阵真是太神奇了。。。。。。。

我比较懒。所以。。。实现了第二种。。。。

 
 
Matrix Power Series
Time Limit: 3000MS Memory Limit: 131072K
Total Submissions: 11648 Accepted: 4977

Description

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

Input

The input contains exactly one test case. The first line of input contains three positive integersn (n ≤ 30), k (k ≤ 109) andm (m < 104). Then follown lines each containing n nonnegative integers below 32,768, givingA’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
#include<iostream>
#include<cstdio>

#define MAXN 100

using namespace std;

struct Matrix
{
    int size;
    long modulo;
    long element[MAXN][MAXN];
    void setSize(int);
    void setModulo(int);
    Matrix operator* (Matrix);
    Matrix power(int);

};

void Matrix::setSize(int a)
{
    for (int i=0; i<a; i++)
        for (int j=0; j<a; j++)
            element[i][j]=0;
    size = a;
}

void Matrix::setModulo(int a)
{
    modulo = a;
}

Matrix Matrix::operator* (Matrix param)
{
    Matrix product;
    product.setSize(size);
    product.setModulo(modulo);
    for (int i=0; i<size; i++)
        for (int j=0; j<size; j++)
            for (int k=0; k<size; k++)
            {
                product.element[i][j]+=element[i][k]*param.element[k][j];
                product.element[i][j]%=modulo;
            }
    return product;
}

Matrix Matrix::power(int exp)
{
    Matrix tmp = (*this) * (*this);
    if (exp==1) return *this;
    else if (exp & 1) return tmp.power(exp/2) * (*this);
    else return tmp.power(exp/2);
}

int n,m,k;
Matrix m1,ans;
int main()
{
    while(~scanf("%d%d%d",&n,&k,&m))
    {
        m1.setModulo(m);
        m1.setSize(n*2);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                scanf("%d",&m1.element[i][j]);
                m1.element[i][j]%=m;
            }
            m1.element[i][i+n]=1;
            m1.element[n+i][n+i]=1;
        }
        m1.element[n][n]=1;
        ans=m1.power(k+1);
        for(int i=0;i<n;i++)
            for(int j=n;j<n*2;j++)
            {
                int out=ans.element[i][j];
                if(j==i+n)
                    out=out==0?m-1:out-1;
                printf("%d%s",out,j!=n*2-1?" ":"\n");
            }
        return 0;

    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值