矩阵快速幂专题(三)

这篇博客是矩阵快速幂专题的最后一部分,博主分享了如何优化矩阵运算以避免TLE和MLE,特别是对于同构矩阵,可以使用一维数组模拟二维矩阵降低复杂度。文中详细分析了几道题目,涉及矩阵变换、循环节的求解、以及如何处理矩阵乘法导致的时间和空间复杂度问题。同时,博主提到未来将转向学习数论算法。
摘要由CSDN通过智能技术生成

哈哈哈,博主又回来了!这次专题是第三弹也是最后一弹了,这次会对矩阵进行一个小收尾。做完这25道题,我感觉到其实我矩阵学得并不好,还有许多知识点没有学会。后面看情况可能还会继续开矩阵的专题,那应该是几个月以后的事了。从下周开始,应该会先学习一下数论的相关算法!

这次的七道题目(为什么题目越来越少了)主要是针对了矩阵的优化,对于会TLE的和MLE(内存爆了)的矩阵而且这个矩阵又恰好是同构矩阵(同构矩阵是啥?)的话,可以采用一维数组来模拟二维,从而降低复杂度、降低空间。(竟然是罕见的同时降时间和空间的做法,但是条件有点苛刻=、=)。




第一题 Fzu-1692

分析:首先要告知读者题目有错误(坑啊!),题目中的( L*A(i+n-1)%n+R*A(i+1)%n )应该改为( R*A(i+n-1)%n+L*A(i+1)%n )就是把L和R交换一下位置,不明白为什么福州大学不改掉,都这么长的时间了。

对于这种换苹果、换火柴的问题,做的太多,感觉一下子就有思路,而且可以说题目上已经把递推式给出了。

对于A[i]来说,一次变换后A[i']=R*A[(i+n-1)%n]+A[i]+L*A[(i+1)%n]

构造矩阵


但是呢,很可惜的是这个算法会超时!我们观察一下矩阵的形式,发现我们构造出来的矩阵有些特殊,每一行与它相邻的一行之间位置关系只差了1个位置(似乎就叫同构矩阵),是一种循环的关系。那么我们根据线性代数的乱七八糟的性质(我不记得了)就可以推到两个同构矩阵相乘得到的矩阵仍然是同构矩阵,那么我们是不是就可以简化运算,只需求结果矩阵的第一行,然后后面的每一行都可以根据前一行与其位置差1的关系,直接推出来,不必一一运算了。

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define clr(x,y) memset(x,y,sizeof(x))
#define rep(i,n) for(int i=0;i<(n);i++)
#define repf(i,a,b) for(int i=(a);i<=(b);i++)
#define maxn 100+5
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IT iterator
#define push_back PB

typedef long long ll;
const double eps = 1e-10;
const double pi  = acos(-1);
const ll mod = 1e9+7; 
const int inf = 0x3f3f3f3f;

ll M;
struct matrix 
{
	int n;
	ll maze[maxn][maxn];
	void init(int n)
	{
		this->n=n;
		clr(maze,0);
	}
	matrix operator * (const matrix & rhs)
	{
		matrix ans;
		ans.init(n);
		rep(j,n)
			rep(k,n)
				ans.maze[0][j]=(ans.maze[0][j]+maze[0][k]*rhs.maze[k][j])%M;
		repf(i,1,n-1)
			rep(j,n)
				ans.maze[i][j]=ans.maze[i-1][(j+n-1)%n];
		return ans;
	}
};
matrix qlow(matrix a,ll n)
{
	matrix ans;
	ans.init(a.n);
	rep(i,a.n)ans.maze[i][i]=1;
	while(n)
	{
		if(n&1)ans=ans*a;
		a=a*a;
		n>>=1;
	}
	return ans;
}
int main()
{
	//freopen("d:\\acm\\in.in","r",stdin);
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,L,R;
		ll m;
		scanf("%d %I64d %d %d %lld",&n,&m,&L,&R,&M);
		matrix ans;
		ans.init(n);
		rep(i,n)scanf("%lld",&ans.maze[0][i]);
		matrix ant;
		ant.init(n);
		rep(i,n)
		{
			ant.maze[i][i]=1;
			ant.maze[(i+n-1)%n][i]=R
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值