蓝桥杯试题 算法训练 小X的暑假作业(矩阵快速幂)

蓝桥杯试题 算法训练 小X的暑假作业

题目描述:

资源限制
时间限制:1.0s 内存限制:128.0MB
问题描述
  小X的作业是老师给他布置的,题目很简单,求出第N个斐波那契数 mod P的值。小X怎么想也想也想不出来,只好求助于你了。
输入格式
  第一行为数据组数T。
  第二行开始,以下T行,每行为老师给小X布置的作业中的N和P。
输出格式
  包含T行,每行是一个作业的答案。
样例输入
3
7 3
1000000 89
987654321 30000
样例输出
0
55
19111
数据规模和约定
  对于50%的数据,T<=100,N<=10000。
  对于100%的数据,T<=10000,N<=1000000000,P<=30000。
  斐波那契数的第0个是1。
  
(可以看到n的值这么大,肯定不能直接用斐波那契的式子)

解题思路:

1 1 2 3 5 8(其中,第一个1是第0项,也就是从第0项开始的斐波那契数列),

目的:求第n项的数值。【这里先忽略取模,暂时讲一下大致思路,不影响,写代码的时候加上取模即可】

我们设第n项为F(n)

由斐波那契的数列性质可以知道,F(n)=F(n-1)+F(n-2)----------------①
而F(n-1)=F(n-1)+0*F(n-2)------------------②【这一步可能会不知道为什么,先往下看,只是为了凑出矩阵A】

由①②两个式子综合可得:

F(n)=F(n-1)+F(n-2)
F(n-1)=F(n-1)+0*F(n-2)

可以推出:一个和矩阵相关的式子(下面)图片有点丑,莫嫌弃,哈哈哈

在这里插入图片描述
然后可以推出,下面这个式子:

在这里插入图片描述
所以F(n)的值就等于矩阵A{1,1,1,0}的n-1次方,乘以{F(1),F(0)},而F(1),F(0)都为1,所以,F(n)的值就等于矩阵A{1,1,1,0}的n-1次方(这里叫做矩阵B),矩阵B的第一行的和(B[0][0]+B[0][1])

所以我们的目标就是算出来A{1,1,1,0}的n-1次方即可,由于n很大很大,就用快速幂的方法做。

快速幂是专门解决a的b次方然后对一个数取模的,只不过这里的a不是一个数值,而是一个确定的矩阵。

点击这里,马上明白快速幂的思路!

AC代码:

#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <math.h>
using namespace std;
long long tt[2][2];
int n,p;
void f(long long a[2][2],long long b[2][2])//计算a矩阵乘以b矩阵的值 
{
	long long temp[2][2];
	int i,j,k;
	memset(temp,0,sizeof(temp));
	for(i=0;i<2;i++)
		for(j=0;j<2;j++)
			for(k=0;k<2;k++)
				temp[i][j]+=a[i][k]*b[k][j];
	for(i=0;i<2;i++)
		for(j=0;j<2;j++)
			tt[i][j]=temp[i][j]%p;//拷贝到tt数组中 
}
int main()
{	
	int t;
	cin>>t;
	while(t--)
	{
		long long t,a[2][2]={1,1,1,0},ans[2][2]={1,0,0,1},temp[2][2];
		memset(temp,0,sizeof(temp));
		cin>>n>>p;
		n--;
		while(n)
		{
			if(n&1)
			{
				f(ans,a);//注意ans初始值为单位矩阵  
				memcpy(ans,tt,sizeof(tt));
			}
			f(a,a);
			memcpy(a,tt,sizeof(tt));
			n>>=1;//右移一位 
		}
		cout<<(ans[0][0]+ans[0][1])%p<<endl;//乘以初始矩阵B(b矩阵上面有说明) 
	}

	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

细水长流者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值