矩阵幂求和 题解

题目大意

给定矩阵 A A A,求 A + A 2 + A 3 + . . . + A k A+A^2+A^3+...+A^k A+A2+A3+...+Ak 中每一个数字对 p p p 取模的结果。

n ≤ 30 , k ≤ 1 0 9 , p ≤ 1 0 4 n \le 30,k \le 10^9,p \le 10^4 n30,k109,p104

思路

先把矩阵乘法、加法、快速幂写出来(不做讲解)。

然后写一个函数 f ( x ) f(x) f(x),返回值为 A + A 2 + A 3 + . . . + A x A+A^2+A^3+...+A^x A+A2+A3+...+Ax

先用 f ( ⌊ x / 2 ⌋ ) f(\lfloor x/2 \rfloor) f(⌊x/2⌋) A + A 2 + A 3 + . . . + A ⌊ x / 2 ⌋ A+A^2+A^3+...+A^{\lfloor x/2 \rfloor} A+A2+A3+...+Ax/2 求出来。

假设 r e s = f ( ⌊ x / 2 ⌋ ) res = f(\lfloor x/2 \rfloor) res=f(⌊x/2⌋),那么

      r e s × A ⌊ x / 2 ⌋ ~~~~~res \times A^{\lfloor x/2 \rfloor}      res×Ax/2

= ( A + A 2 + A 3 + . . . + A ⌊ x / 2 ⌋ ) × A ⌊ x / 2 ⌋ =(A+A^2+A^3+...+A^{\lfloor x/2 \rfloor}) \times A^{\lfloor x/2 \rfloor} =(A+A2+A3+...+Ax/2)×Ax/2

= A × A ⌊ x / 2 ⌋ + A 2 × A ⌊ x / 2 ⌋ + A 3 × A ⌊ x / 2 ⌋ + . . . + A ⌊ x / 2 ⌋ × A ⌊ x / 2 ⌋ =A \times A^{\lfloor x/2 \rfloor}+A^2 \times A^{\lfloor x/2 \rfloor}+A^3 \times A^{\lfloor x/2 \rfloor}+...+A^{\lfloor x/2 \rfloor} \times A^{\lfloor x/2 \rfloor} =A×Ax/2+A2×Ax/2+A3×Ax/2+...+Ax/2×Ax/2

= A ⌊ x / 2 ⌋ + 1 + A ⌊ x / 2 ⌋ + 2 + A ⌊ x / 2 ⌋ + 3 + . . . + A ⌊ x / 2 ⌋ + ⌊ x / 2 ⌋ =A^{{\lfloor x/2 \rfloor}+1}+A^{{\lfloor x/2 \rfloor}+2}+A^{{\lfloor x/2 \rfloor}+3}+...+A^{{\lfloor x/2 \rfloor}+{\lfloor x/2 \rfloor}} =Ax/2+1+Ax/2+2+Ax/2+3+...+Ax/2+x/2

这样就可以得出:

      r e s + r e s × A ⌊ x / 2 ⌋ ~~~~~res+res \times A^{\lfloor x/2 \rfloor}      res+res×Ax/2

= ( A + A 2 + A 3 + . . . + A ⌊ x / 2 ⌋ ) + ( A ⌊ x / 2 ⌋ + 1 + A ⌊ x / 2 ⌋ + 2 + A ⌊ x / 2 ⌋ + 3 + . . . + A ⌊ x / 2 ⌋ + ⌊ x / 2 ⌋ ) =(A+A^2+A^3+...+A^{\lfloor x/2 \rfloor})+(A^{{\lfloor x/2 \rfloor}+1}+A^{{\lfloor x/2 \rfloor}+2}+A^{{\lfloor x/2 \rfloor}+3}+...+A^{{\lfloor x/2 \rfloor}+{\lfloor x/2 \rfloor}}) =(A+A2+A3+...+Ax/2)+(Ax/2+1+Ax/2+2+Ax/2+3+...+Ax/2+x/2)

= A + A 2 + A 3 + . . . + A ⌊ x / 2 ⌋ × 2 =A+A^2+A^3+...+A^{{\lfloor x/2 \rfloor\times 2}} =A+A2+A3+...+Ax/2×2

那么,当 x x x 为偶数, ⌊ x / 2 ⌋ × 2 = x \lfloor x/2 \rfloor\times 2=x x/2×2=x,所以 r e s + r e s × A ⌊ x / 2 ⌋ res+res \times A^{\lfloor x/2 \rfloor} res+res×Ax/2 即为答案。

x x x 为奇数, ⌊ x / 2 ⌋ × 2 = x − 1 \lfloor x/2 \rfloor\times 2=x-1 x/2×2=x1,所以 r e s + r e s × A ⌊ x / 2 ⌋ = A + A 2 + A 3 + . . . + A x − 1 res+res \times A^{\lfloor x/2 \rfloor}=A+A^2+A^3+...+A^{x-1} res+res×Ax/2=A+A2+A3+...+Ax1,所以这个结果加上 A x A^x Ax 即为答案。

因为每次递归只需要求 f ( ⌊ x / 2 ⌋ ) f(\lfloor x/2 \rfloor) f(⌊x/2⌋),所以时间复杂度为 O ( log ⁡ k ) \mathcal{O}(\log k) O(logk)

摆上代码

matrix a;//输入的矩阵

matrix f(int x)
{
    if(x==1) return a;//当x==1,答案就是a.
    matrix res=f(x/2);//求出f(⌊x/2⌋)
    if(x%2==0) return res+(qpow(a,x/2)*res);//当x为偶数,答案为res+res×A^⌊x/2⌋
    else return res+(res*qpow(a,x/2))+qpow(a,x);//否则答案就是 res+res×A^⌊x/2⌋+A^x
}

完整代码

#include<bits/stdc++.h>
using namespace std;
int n,k,p;
struct matrix
{
	int a[35][35];
	matrix operator *(matrix b)//矩阵乘法
	{
		matrix res;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
			{
				res.a[i][j]=0;
				for(int k=1;k<=n;k++)
				{
					res.a[i][j]=(res.a[i][j]+a[i][k]*b.a[k][j])%p;
				}
			}
		return res;
	}
	
	matrix operator +(matrix b)//矩阵加法
	{
		matrix res;
	    for(int i=1;i<=n;i++)
	        for(int j=1;j<=n;j++)
	            res.a[i][j]=(a[i][j]+b.a[i][j])%p;
	    return res;
	}
};

matrix qpow(matrix a,int k)//快速幂
{
    matrix res;
   	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) res.a[i][j]=0;//清空
    for(int i=1;i<=n;i++) res.a[i][i]=1;//把res变成单位矩阵
    //单位矩阵性质:一个矩阵乘以单位矩阵=这个矩阵。
    while(k)
    {
        if(k&1) res=res*a;
        a=a*a;
        k>>=1;
    }
    return res;
}

matrix a;

matrix f(int x)
{
    if(x==1) return a;//当x==1,答案就是a.
    matrix res=f(x/2);//求出f(⌊x/2⌋)
    if(x%2==0) return res+(qpow(a,x/2)*res);//当x为偶数,答案为res+res×A^⌊x/2⌋
    else return res+(res*qpow(a,x/2))+qpow(a,x);
}

matrix ans;

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>k>>p;
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) cin>>a.a[i][j],a.a[i][j]%=p;//读入矩阵
		
	ans=f(k);//求出这个矩阵
	
	for(int i=1;i<=n;i++)//直接输出矩阵就可以了
	{
		for(int j=1;j<=n;j++) cout<<ans.a[i][j]%p<<" ";
		cout<<endl;
	}
	return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值