哈哈哈,博主又回来了!这次专题是第三弹也是最后一弹了,这次会对矩阵进行一个小收尾。做完这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