【矩阵快速幂专题】清华大学考研复试上机——递推数列

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qian2213762498/article/details/82154850

点击打开链接

递推数列          

时间限制:1秒 空间限制:65536K 热度指数:4721

 算法知识视频讲解

题目描述

给定a0,a1,以及an=p*a(n-1) + q*a(n-2)中的p,q。这里n >= 2。 求第k个数对10000的模。

输入描述:

输入包括5个整数:a0、a1、p、q、k。

输出描述:

第k个数a(k)对10000的模。

示例1

输入

20 1 1 14 5

输出

8359

几个月前做这道题的时候,我还不知什么是矩阵快速幂;

当时只是想着简单递推的方式做,牛客网是可以AC的,但是据说递推的方法在九度OJ上Runtime Error。

于是此题就变成一道裸的矩阵快速幂模板题,关键在于递推矩阵的构造。

递推法

#include <iostream>
#include<cstring>
using namespace std;
const int nmax=1e4;
int a[nmax];
 
int main(int argc, char** argv) {
	int a0,a1;
	int p,q,k;
	int ans;
	while(cin>>a0>>a1>>p>>q>>k){
		memset(a,0,sizeof(a));
		a[0]=a0;a[1]=a1;
		for(int i=2;i<=k;i++){
			a[i]=(p*a[i-1]+q*a[i-2])%10000;
		}
		ans=a[k];
		cout<<ans<<endl;
	}
	return 0;
}

矩阵快速幂

当n很大时,只能采用矩阵快速幂了。

本题中初始矩阵、递推矩阵如下:

AC Code

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const ll nmax=3;
const ll MOD=10000;
#define mod(x) ((x)%MOD)
 
int n;
struct mat{
	ll m[nmax][nmax];
}unit;
 
//A*B^(n-2)=C //C矩阵的首项即为f(n) 
mat operator *(mat a,mat b){
	mat ret;
	ll x;
	for(ll i=0;i<nmax;i++){//3*3
		for(int j=0;j<nmax;j++){
			x=0;
			for(ll k=0;k<nmax;k++){
				x+=mod((ll)a.m[i][k]*b.m[k][j]);
			}
			ret.m[i][j]=mod(x);
		}
	}
	return ret;
}
 
void init_unit(){
	for(ll i=0;i<nmax;i++){
		unit.m[i][i]=1;
	} 
	return;
}
mat pow_mat(mat a,ll n){//求矩阵a的n次幂 
	mat ret=unit;
	while(n){
		if(n&1) ret=ret*a;
		a=a*a;
		n>>=1;
	} 
	return ret;
}
int main(int argc, char** argv) {
	ll a0,a1,p,q,k;
	init_unit();
	while(cin>>a0>>a1>>p>>q>>k){
		if(k==0) printf("%lld\n",mod(a0));
		else if(n==1) printf("%lld\n",mod(a1));
		else{
			mat a,b;
			ll a2=p*a1+q*a0;
			//cout<<a1<<" "<<a0<<" "<<p<<" "<<q<<" "<<k<<endl; 
			//cout<<a2<<endl;
			b.m[0][0]=p;b.m[0][1]=1;b.m[0][2]=0;
			b.m[1][0]=q;b.m[1][1]=0;b.m[1][2]=1;
			b.m[2][0]=0;b.m[2][1]=0;b.m[2][2]=0;
			
			a.m[0][0]=a2;a.m[0][1]=a1;a.m[0][2]=a0;
            a.m[1][0]=0; a.m[1][1]=0; a.m[1][2]=0;
            a.m[2][0]=0; a.m[2][1]=0; a.m[2][2]=0;
			b=pow_mat(b,k-2);
			a=a*b;
			//printf("%lld\n",mod(a.m[0][0]));
			printf("%lld\n",a.m[0][0]%MOD);
		} 
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qian2213762498/article/details/82154850
今日推荐