快速求斐波那契数列(矩阵乘法+快速幂)

斐波那契数列

给你一个n;f(n)=f(n-1)+f(n-2)

请求出 f(f(n)),由于结果很大请

对答案 mod 10^9+7;

1<=n<=10^100;

用矩阵乘法+快速幂求斐波那契数列是经典应用;

矩阵公式 C i j=C i k *C k j;

根据递推式 构造2*2矩阵;

原始矩阵

1 0

0 1

矩阵 2

1 1

1 0

原始矩阵与矩阵 2相乘达到转化状态效果;

对矩阵二进行快速幂 乘法;达到快速转化矩阵的效果;

即使达到快速转化状态;那么大的数据范围也很难求解;

高精?这有一种不用高精的方法;

打个暴力 求循环节;

即 f(f(n))%mod同余f(f(n%k)%p)%mod;

暴力求k p 即可;

k=6e9+6;p=2e9+2;

以下暴力程序

#include<cstdio>
typedef long long LL;
LL  f[100005],k;
int main(){
	f[1]=1;k=1;
	while (1){
		k++;
		f[2]=(f[1]+f[0])%1000000007;
		if (f[2]==2) {
			printf("%lld\n",k);
		}
		f[0]=f[1];
		f[1]=f[2];
	}
}

 AC 程序

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#define mod 1000000007
#define ll long long
int T,i,j,k;
ll n;
ll a[2][2],b[2][2],c[2][2],f[2][2];
char ch;
void Mod(ll mo)
{
	n=0;
	ll q=getchar();
	while(q<48||q>57)q=getchar();
	while(q>=48&q<=57)
	{
		n=(n*10+q-48)%mo;
		q=getchar();
	}
}
void mul(ll a[2][2],ll b[2][2],ll mo)
{
	ll c[2][2]={0};
	for(i=0;i<2;++i)
	for(j=0;j<2;++j)
	for(k=0;k<2;++k)
	c[i][j]=(c[i][j]+a[i][k]*b[k][j]%mo)%mo;
	for(i=0;i<2;++i)
	for(j=0;j<2;++j)
	a[i][j]=c[i][j];
}
int main()
{
//	freopen("xx.in","r",stdin);
//	freopen("xx.out","w",stdout);
	scanf("%d\n",&T);
	for(;T--;)
	{
		Mod(mod*6ll+6);
		if(n<=2)
		{
			if(!n)printf("0\n");
			else printf("1\n");
			continue;
		}
		n-=1;
		a[0][0]=a[0][1]=a[1][0]=1;a[1][1]=0;
		f[0][0]=f[1][1]=1;f[1][0]=f[0][1]=0;
		while(n)
		{
			if(n&1)mul(f,a,mod*2ll+2);
			mul(a,a,mod*2ll+2);
			n>>=1;
		}
		n=f[0][0]-1;
		a[0][0]=a[0][1]=a[1][0]=1;a[1][1]=0;
		f[0][0]=f[1][1]=1;f[1][0]=f[0][1]=0;
		while(n)
		{
			if(n&1)mul(f,a,mod);
			mul(a,a,mod);
			n>>=1;
		}
		printf("%d\n",f[0][0]);
	}
}

  

问题描述】

令??(??)为斐波那契数列第??项,其中??(0) = 0,??(1) = 1,??(??) = ??(??? 1) +??(?? ?2)。所以要干啥呢?求??(??(??))。【输入格式】第一行一个整数??代表数据组数。接下来??行每行一个整数??。【输出格式】??行每行一个整数代表答案对10 9 + 7取模的值。【样例输入】40126【样例输出】01121【样例解释】无。【数据规模与约定】215 490。70%的数据,1 ≤ ?? ≤ 10 5 。对于100%的数据,1 ≤ ?? ≤ 10 3 ,1 ≤ ?? ≤ 10 100 。

时间: 2024-12-07 19:15:51

快速求斐波那契数列(矩阵乘法+快速幂)的相关文章

P1349 广义斐波那契数列(矩阵乘法)

题目 P1349 广义斐波那契数列 解析 把普通的矩阵乘法求斐波那契数列改一改,随便一推就出来了 \[\begin{bmatrix}f_2\\f_1 \end{bmatrix}\begin{bmatrix} p&q\1&0\\end{bmatrix}^{n-2}=\begin{bmatrix}f_n\\f_{n-1} \end{bmatrix}\] 水题 代码 #include <bits/stdc++.h> #define int long long using namesp

洛谷P1962 斐波那契数列 || P1349 广义斐波那契数列[矩阵乘法]

P1962 斐波那契数列 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数) 题目描述 请你求出 f(n) mod 1000000007 的值. 输入输出格式 输入格式: ·第 1 行:一个整数 n 输出格式: 第 1 行: f(n) mod 1000000007 的值 输入输出样例 输入样例#1: 5 输出样例#1: 5 输入样例#2: 10 输出样例#2: 55 说明

快速求斐波那契数列&lt;黄金分割率&gt;

有一个固定的数学公式= =,不知道的话显然没法应用 a(n)为斐波那契数第n项 O(1)复杂度 Python def fib(self, N): golden_ratio = (1 + 5 ** 0.5) / 2 return int((golden_ratio ** N + 1) / 5 ** 0.5) 原文地址:https://www.cnblogs.com/shitianfang/p/12347963.html

poj 3070 Fibonacci (矩阵快速幂求斐波那契数列的第n项)

题意就是用矩阵乘法来求斐波那契数列的第n项的后四位数.如果后四位全为0,则输出0,否则 输出后四位去掉前导0,也...就...是...说...输出Fn%10000. 题目说的如此清楚..我居然还在%和/来找后四位还判断是不是全为0还输出时判断是否为0然后 去掉前导0.o(╯□╰)o 还有矩阵快速幂的幂是0时要特判. P.S:今天下午就想好今天学一下矩阵乘法方面的知识,这题是我的第一道正式接触矩阵乘法的题,欧耶! #include<cstdio> #include<iostream>

【poj3070】矩阵乘法求斐波那契数列

[题目描述] 我们知道斐波那契数列0 1 1 2 3 5 8 13…… 数列中的第i位为第i-1位和第i-2位的和(规定第0位为0,第一位为1). 求斐波那契数列中的第n位mod 10000的值. [分析] 这是我们熟悉的斐波那契数列,原来呢我们是递推求值的嘛,当然这是最水的想法~~可是!这里的n很大诶,有10^9,for一遍肯定是不可以的咯. 于是,我学会了用矩阵乘法求斐波那契数列(貌似是很经典的). 作为初学者的我觉得十分神奇!! 好,我们来看: 我们每次存两个数f[i-1]和f[i-2],

利用矩阵求斐波那契数列

利用矩阵求斐波那契数列 flyfish 2015-8-27 矩阵(matrix)定义 一个m*n的矩阵是一个由m行n列元素排成的矩形阵列.矩阵里的元素可以是数字符号或者数学式. 形如 {acbd} 的数表称为二阶矩阵,它由二行二列组成,其中a,b,c,d称为这个矩阵的元素. 形如 {x1x2} 的有序对称为列向量Column vector 设 A={acbd} X={x1x2} 则 Y={ax1+bx2cx1+dx2} 称为二阶矩阵A与平面向量X的乘积,记为AX=Y 斐波那契(Fibonacci

HDU 4549 M斐波那契数列 ( 矩阵快速幂 + 费马小定理 )

HDU 4549 M斐波那契数列 (  矩阵快速幂 + 费马小定理  ) 题意:中文题,不解释 分析:最好的分析就是先推一推前几项,看看有什么规律 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef __int64 LL; #define CLR( a, b ) memset( a, b, sizeof(a) ) #define MOD 100000

c语言:写一个函数,输入n,求斐波拉契数列的第n项(5种方法,层层优化)

写一个函数,输入n,求斐波拉契数列的第n项. 斐波拉契数列:1,1,2,3,5,8...,当n大于等于3时,后一项为前面两项之和. 解:方法1:从斐波拉契数列的函数定义角度编程 #include<stdio.h> int fibonacci(int n) { int num1=1, num2=1, num3=0,i; if (n <= 2) { printf("斐波拉契数列的第%d项为:%d\n",n,num1); } else { for (i = 2; i <

求斐波那契数列的第n个数(递归、非递归)

用递归的方式求斐波那契数列的第n个数. 用非递归的方式求斐波那契数列的第n个数. 定义: 斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368 特别指出:第0项是0,第1项是第一个1. 这个数列从第2项开始,每一项都等于前两项之和. #include<stdio.h> #include<stdlib.