ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

数列变换题解

2022-07-28 13:00:52  阅读:138  来源: 互联网

标签:begin end 数列 变换 题解 矩阵 long times bmatrix


题解

题目传送门

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有