poj3233 Matrix Power Series

Time Limit: 3000MS Memory Limit: 131072K
Total Submissions: 18578 Accepted: 7858

Description

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

这题可以用矩阵快速幂做。列方程知道dp[i]=dp[i-1]+A[i],所以可以构造矩阵

【A^i,dp[i-1]】*B=【A^(i+1),dp[i]】

其中B=A E

E E

其中E是单位矩阵。

为了方便,可以使得【A^i,dp[i-1]】补成A^i dp[i-1]

0 1

这样就是求B^(k+1)次了

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
#define inf 99999999
#define pi acos(-1.0)

ll MOD;
struct matrix{
    ll n,m,i;
    ll data[80][80];
    void init_danwei(){
        for(i=0;i<n;i++){
            data[i][i]=1;
        }
    }
}a;

matrix multi(matrix &a,matrix &b){
    ll i,j,k;
    matrix temp;
    temp.n=a.n;
    temp.m=b.m;
    for(i=0;i<temp.n;i++){
        for(j=0;j<temp.m;j++){
            temp.data[i][j]=0;
        }
    }
    for(i=0;i<a.n;i++){
        for(k=0;k<a.m;k++){
            if(a.data[i][k]>0){
                for(j=0;j<b.m;j++){
                    temp.data[i][j]=(temp.data[i][j]+(a.data[i][k]*b.data[k][j])%MOD )%MOD;
                }
            }
        }
    }
    return temp;
}

matrix fast_mod(matrix &a,ll n){
    matrix ans;
    ans.n=a.n;
    ans.m=a.m;
    memset(ans.data,0,sizeof(ans.data));
    ans.init_danwei();
    while(n>0){
        if(n&1)ans=multi(ans,a);
        a=multi(a,a);
        n>>=1;
    }
    return ans;
}




int main()
{
    ll n,m,i,j,k;
    while(scanf("%lld%lld%lld",&n,&k,&MOD)!=EOF)
    {
        memset(a.data,0,sizeof(a.data ));
        for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                scanf("%lld",&a.data[i][j]);
            }
        }
        a.n=a.m=2*n;
        for(i=0;i<n;i++){
            a.data[i][i+n]=a.data[i+n][i+n]=1;
        }
        matrix cnt;
        cnt=fast_mod(a,k+1);
        int c;
        for(i=0;i<n;i++){
            int flag=1;
            for(j=0;j<n;j++){
                if(i==j){
                    cnt.data[i][j+n]--;
                }
                if(flag){
                    flag=0;printf("%lld",(cnt.data[i][j+n]+MOD)%MOD  );
                }
                else printf(" %lld",(cnt.data[i][j+n]+MOD)%MOD  );
            }
            printf("\n");
        }
    }
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值