其他分享
首页 > 其他分享> > 数列变换题解

数列变换题解

作者:互联网

题解

题目传送门

1.分析题目

1.矩阵乘法

如果想要\(AC\)这道题,就需要学习矩阵乘法。顾名思义,矩阵乘法就是矩阵乘矩阵的运算。

矩阵乘法的运算法则如下:
现有一个\(N \times P\)的矩阵\(A\)和一个\(P \times M\)的矩阵\(B\),令矩阵\(C=A\times B\),则\(C_{i,j}=\sum\limits_{k=1}^{P}A_{i,k}\times B_{k,j}\)。

如\(\begin{bmatrix}1&1&2 \\ 3&2&4\end{bmatrix} \times \begin{bmatrix}1\\3\\2\end{bmatrix}=\begin{bmatrix}1\times1+1\times3+2\times2 \\ 3\times1+2\times3+4\times2\end{bmatrix}=\begin{bmatrix}8\\17\end{bmatrix}\)

经典问题\(Fibonacci\)数列就可以用矩阵乘法解决。

我们需要一个基础矩阵\(A\),大小为\(1\times2\)。我们在矩阵中维护两个信息:数列中当前数的数值以及前一个数的数值。比如基础矩阵\(A=\begin{bmatrix}0&1\end{bmatrix}\),表示第一个数为一,通关计算得到第零个数为0。我们还需要一个常数矩阵\(B=\begin{bmatrix}0&1\\1&1\end{bmatrix}\),每次将\(A\)更新为\(A\times B\),就可以得到\(A\)的下一个状态。循环\(N\)次后,\(A_{1,2}\)即位\(Fib_N\)。

此时,我们通过观察\(A=A\times B\)这个式子,不难发现\(A\)其实只是乘上了\(B^N\),这让我们不禁又想起了快速幂这个好东西。

2.快速幂

如果想求\(a^x\)是多少,最粗暴的方式就是枚举,那有没有什么算法可以优化呢?

当然有!我们只需要将\(x\)进行二进制拆分,从低位到高位进行枚举。如果这位是一,每次将结果\(ans\)乘上\(a^{2^i}\)就可以了。

\(Code:\)

void Pow(long long a,int x){
    long long tmp=a,ans=1ll;
    for(;x;x>>=1){
        if(x&1){
            ans*=tmp;
        }
        tmp*=tmp;
    }
}

用快速幂求\(Fibonacci\):

long long a[2]={0,1},b[2][2]={{0,1},{1,1}};
void mul_self(){
    long long c[2][2]={{0,0},{0,0}};
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            for(int k=0;k<2;k++){
                c[i][j]+=b[i][k]*b[k][j];
            }
        }
    }
}
void mul(){
    long long c[2]={0,0};
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            c[i]+=a[j]*b[j][i];
        }
    }
}
void Pow(int n){
    for(;n;n>>=1){
        if(n&1)mul();
        mul_self();
    }
}

3.回归题目

回到题目,我们可以把这道题和\(Fibonacci\)数列题目类比起来,不难发现,基础矩阵\(A=\begin{bmatrix}x_1,x_2,\cdots,x_n\end{bmatrix}\),常数矩阵\(B=\begin{bmatrix}0&0&0&\cdots&a_1 \\ 1&0&0&\cdots&a_2\\0&1&0&\cdots&a_3\\\vdots&\vdots&\vdots&\ddots&\vdots\\0&0&0&\cdots&a_n\end{bmatrix}\),将这两个矩阵按照上面的方法进行操作即可

代码

\(Code:\)

#include<bits/stdc++.h>
#include<cstdio>
using namespace std;
const long long M=998244353;
int n;
long long m,a[105],x[105];
long long matrix[105][105];
void fast(){
	for(;m;m>>=1){
		if(m&1){
			long long X[105];
			memset(X,0,sizeof(X));
			for(int i=1;i<=n;i++){
				for(int j=1;j<=n;j++){
					X[i]+=x[j]*matrix[j][i];
					X[i]%=M;
				}
			}
			memcpy(x,X,sizeof(X));
		}
		long long Matrix[105][105];
		memset(Matrix,0,sizeof(Matrix));
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				for(int k=1;k<=n;k++){
					Matrix[i][j]+=matrix[i][k]*matrix[k][j];
					Matrix[i][j]%=M;
				}
			}
		}
		memcpy(matrix,Matrix,sizeof(Matrix));
	}
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>a[i],a[i]%=M;
	for(int i=1;i<=n;i++)cin>>x[i],x[i]%=M;
	for(int i=1;i<n;i++)matrix[i+1][i]=1;
	for(int i=1;i<=n;i++)matrix[i][n]=a[i];
	m-=n;
	fast();
	cout<<x[n];
}
/*
C[1][j]=A[1][i]*B[i][j]
*/

标签:begin,end,数列,变换,题解,矩阵,long,times,bmatrix
来源: https://www.cnblogs.com/easonhe/p/16528257.html