Matrix Power Series 矩阵快速幂 + 因式分解(分治)

本文介绍了一种使用矩阵快速幂算法解决特定矩阵求和问题的方法。对于给定的n×n矩阵A和正整数k,算法高效计算从A到Ak的所有矩阵相加的和,并输出结果模m后的矩阵。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.

 思路  A1+A2+A3+A4+A5+A6= A1+A2+A3 + A3(A1+A2+A3)

                                                  = (A1+A2+A3) *( A3+I)  // I 是单位矩阵;

                                                 =( A1*(A1+I)+A3) * (A3+ I );

     采用分治的思想,不断二分……

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<set>
#include<queue>
#include<map>
#include<vector>
using namespace std;
int k,n,mod;
struct node{
  int w[40][40];
  void init(){
      for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
          scanf("%d",&w[i][j]);
  }
  void prf(){
    for(int i=0;i<n;i++){
      for(int j=0;j<n-1;j++) printf("%d ",w[i][j]);
      printf("%d\n",w[i][n-1]);
    }
  }
  node operator * (const node &b) const{
     node cur;
     memset(cur.w,0,sizeof(cur.w));
     for(int i=0;i<n;i++){
       for(int j=0;j<n;j++){
         for(int k=0;k<n;k++){
            cur.w[i][j]=(cur.w[i][j]+(w[i][k]*b.w[k][j])%mod)%mod;
         }
       }
     }
     return cur;
  }
  node operator + (const node &b) const{
    node cur ;
    for(int i=0;i<n;i++)
      for(int j=0;j<n;j++) cur.w[i][j]=(w[i][j]+b.w[i][j])%mod;
    return cur;
  }
};
node a,ans,I,tp;
node check(int x){
    node cur=I,p=a;
    while(x){
       if(x&1) cur=cur*p;
       p=p*p;
       x>>=1;
    }
    return cur;
}
void dfs(int num){
    if(num==1)  return;
    dfs(num/2);
    tp=check(num/2);
    ans=ans*(tp+I);
    if(num&1){
      tp=check(num);
      ans=ans+tp;
    }
}
int  main()
{
//    freopen("in.in","r",stdin);
    memset(I.w,0,sizeof(I.w));
    while(~scanf("%d%d%d",&n,&k,&mod)){
       a.init();
       ans=a;
       for(int i=0;i<n;i++) I.w[i][i]=1;
       dfs(k);
       ans.prf();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值