洛谷P1962 斐波那契数列【矩阵运算】
洛谷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
说明
对于 60% 的数据: n ≤ 92
对于 100% 的数据: n在long long(INT64)范围内。
题解分析:
这题主要的难点就在超大的数据范围
” n在long long(INT64)范围内。”
直接递推什么的肯定是不行的
所以这时候我们的矩阵运算就派上用场啦
我们依次将斐波那契数放入矩阵
一号矩阵是已知的
那么要怎样推出后面的矩阵呢
我们试着用1矩阵乘以下面这个矩阵A
发现是不是得到了二号矩阵
再用二号矩阵去乘A矩阵
是不是得到了三号?
(真的是妙啊~妙啊~)
由此不难找出规律
f(n)第一次出现的地方
就是算出A^(n-2)再乘以原斐波那契初始矩阵
最后要求的f(n)一定在答案矩阵的最下面的位置
所以总结起来
矩阵运算的题目
就是像这样找出一个初始矩阵
然后便可以运用该矩阵进行优化运算
规律应该很清楚了吧
代码里就不写什么注释了
(就是懒 = =)
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
ll read()
{
ll f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
void print(ll x)
{
if(x<0){putchar('-');x=-x;}
if(x>9)print(x/10);
putchar(x%10+'0');
}
const ll mod=1000000007;
ll n;
struct node
{
ll a[5][5];
node()
{
for(ll i=1;i<=2;i++)
for(ll j=1;j<=2;j++)
a[i][j]=0;
}//初始化矩阵
}d,fibo;
ll res[10][10];
node quick_pow(node f,ll k)
{
if(k==1) return f;
else if(k%2==1)
{
node temp=quick_pow(f,k-1);
node ans;
for(ll i=1;i<=2;i++)
for(ll j=1;j<=2;j++)
for(ll k=1;k<=2;k++)
ans.a[i][j]+=(f.a[i][k]*temp.a[k][j])%mod,ans.a[i][j]%=mod;
return ans;
}
else if(k%2==0)
{
node temp=quick_pow(f,k/2);
node ans;
for(ll i=1;i<=2;i++)
for(ll j=1;j<=2;j++)
for(ll k=1;k<=2;k++)
ans.a[i][j]+=(temp.a[i][k]*temp.a[k][j])%mod,ans.a[i][j]%=mod;
return ans;
}
}
int main()
{
n=read();
if(n==1||n==2){print(1);return 0;}
//记得特判
fibo.a[1][1]=1; fibo.a[2][1]=1;
d.a[1][1]=0; d.a[1][2]=1;
d.a[2][1]=1; d.a[2][2]=1;
//运算用的矩阵
ll k=n-2;
node temp=quick_pow(d,k);
//先计算A矩阵的n-2次幂
for(ll i=1;i<=2;i++)
for(ll j=1;j<=1;j++)
for(ll k=1;k<=2;k++)
res[i][j]+=(temp.a[i][k]*fibo.a[k][j])%mod,res[i][j]%=mod;
//与f(1)与f(2)的矩阵相乘得出最后答案矩阵
print(res[2][1]);
return 0;
}
洛谷P1962 斐波那契数列【矩阵运算】的更多相关文章
- 洛谷P1962 斐波那契数列 || P1349 广义斐波那契数列[矩阵乘法]
P1962 斐波那契数列 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数 ...
- 洛谷——P1962 斐波那契数列
P1962 斐波那契数列 题目背景 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 ...
- 洛谷—— P1962 斐波那契数列
https://www.luogu.org/problem/show?pid=1962 题目背景 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f ...
- 洛谷P1962 斐波那契数列(矩阵快速幂)
题目背景 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数) 题目描述 请 ...
- 洛谷P1962 斐波那契数列题解
题目背景 大家都知道,斐波那契数列是满足如下性质的一个数列: • f(1) = 1 • f(2) = 1 • f(n) = f(n-1) + f(n-2) (n ≥ 2 且 n 为整数) 题目描述 请 ...
- 【洛谷P1962 斐波那契数列】矩阵快速幂+数学推导
来提供两个正确的做法: 斐波那契数列双倍项的做法(附加证明) 矩阵快速幂 一.双倍项做法 在偶然之中,在百度中翻到了有关于斐波那契数列的词条(传送门),那么我们可以发现一个这个规律$ \frac{F_ ...
- 洛谷 P1962 斐波那契数列
题目链接:https://www.luogu.org/problemnew/show/P1962 题目大意: 略 分析: 由于数据规模很大,需要用矩阵快速幂来解. 代码如下: #pragma GCC ...
- 题解——洛谷P1962 斐波那契数列(矩阵乘法)
矩阵乘法加速线性递推的典型 大概套路就是先构造一个矩阵\( F \)使得另一初始矩阵\( A \)乘以\( F^{x} \)能够得出第n项 跑的飞快 虽然我也不知道那个矩阵要怎么构造 或许就像我使用了 ...
- 洛谷P1962 斐波那契数列
传送门 不难得到状态转移矩阵 然后带进去乱搞 //minamoto #include<iostream> #include<cstdio> #include<cstrin ...
随机推荐
- servlet入门学习之工作原理解析
从 Servlet 容器说起 要介绍 Servlet 必须要先把 Servlet 容器说清楚,Servlet 与 Servlet 容器的关系有点像枪和子弹的关系,枪是为子弹而生,而子弹又让枪有了杀伤力 ...
- Github终于连上了hexo
2018-01-2722:59:28 我的妈呀,看看这感人的网速,哎不想吐槽在中国连外网的速度 总结一下连接过程吧 漫漫长征路,难的要死. 一.github的注册和使用不再详述 二.Git Desk ...
- python3 第十四章 - 数据类型之Dictionary(字典)
在python中字典是另一种可变容器模型,且可存储任意类型对象. 字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中 ,格式如下 ...
- Java与C/C++的区别
首先应该清楚,Java是由C++发展而来的,它保留了c++的大部分内容,类似于c++,但句法更清晰,规模更小,更易学.它是在对多种程序设计语言进行了深入细致研究的基础上,据弃了其他语言的不足之 ...
- 利用JS判断浏览器种类
现在浏览器很多,写代码的时候常常存在兼容性问题,所以判断用户使用的浏览器很重要.userAgent带有浏览器的种类及版本号等信息,所以可以通过userAgent属性来判断.一些冷门的浏览器,可以通过打 ...
- Android4.0新控件
谷歌在推出Android4.0的同时推出了一些新控件,Android4.0中最常用的新控件有下面5种. 1. Switch的使用 Switch顾名思义,就是开关的意思,有开和关两种状态. 当Swit ...
- zabbix_sender用法实例
环境centos6.8 zabbix版本3.2.4 需求: 要远程监控一台服务器A,但只能通过远程服务器连接本地服务器B,但B不能主动连A(因为A没有固定公网ip) 使用了zabbix_agent的a ...
- 结合find和cp批量查找文件并复制到指定文件夹中
find . -name JA1_*001_027 | xargs -i cp {} F:/ 说明: . 表示当前文件夹及其子文件夹中查找 -name 指定待查找文件,可以使用通配符 F:/ 表示 ...
- 在UITableView顶部制作简单的UISegmentControl实例方法
// http://www.tuicool.com/articles/yUfURj 使用方法 如上图: 分两步: 一.创建320长度背景,高不超过40最好 //segment背景图 UIImageVi ...
- The man Command
The man command is used to format and display the man pages. The man pages are a user manual that is ...