矩阵快速幂--51nod-1242斐波那契数列的第N项
斐波那契额数列的第N项
斐波那契数列的定义如下:
F(0) = 0
F(1) = 1
F(n) = F(n - 1) + F(n - 2) (n >= 2)
(1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, ...)
给出n,求F(n),由于结果很大,输出F(n) % 1000000009的结果即可。
输入
输入1个数n(1 <= n <= 10^18)。
输出
输出F(n) % 1000000009的结果。
输入样例
11
输出样例
89
思路
矩阵快速幂的模板
下面是快速幂的模板,具体怎么来的请自行百度,我们将根据这个模板写矩阵快速幂
LL Qpow(LL a, LL b)
{
LL ret = 1, base = a;
while(b)
{
if(b & 1)
ret *= base;
base *= base;
b >>= 1;
}
return ret;
}
当我们用矩阵代替底数a时,这就涉及到ret和base的初始化和矩阵乘法
所以得出下面矩阵快速幂的模板
struct M
{
LL m[N][N];
};
M mul(M a, M b, int n)
{
M t;
//初始化
for(int i = 1;i <= n;++i)
for(int j = 1;j <= n;++j)
t.m[i][j] = 0;
//乘法运算
for(int i = 1;i <= n;++i)
for(int j = 1;j <= n;++j)
for(int k = 1;k <= n;++k)
t.m[i][j] = (t.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;//取模,视题目而定
return t;
}
M M_Qpow(M a, LL b, int n)
{
M ret, base;
//初始化,根据快速幂中,ret = 1,ret初始化成单位矩阵
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= n;++j)
{
ret.m[i][j] = 0;
ret.m[i][i] = 1;
base.m[i][j] = a.m[i][j];
}
}
//注意矩阵乘法中a*b != b*a
while(b)
{
if(b & 1)
ret = mul(ret, base, n);
base = mul(base, base, n);
b >>= 1;
}
return ret;
}
这道题中,构造这样的矩阵[fn, fn - 1] * b = [fn + 1, fn],然后求矩阵b,这个矩阵容易推算出来
b = [1, 1
1, 0]
解题代码
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <sstream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <iomanip>
#include <stack>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int N = 105;
const int MOD = 1e9 + 9;
struct M
{
LL m[N][N];
};
M mul(M a, M b, int n)
{
M t;
//初始化
for(int i = 1;i <= n;++i)
for(int j = 1;j <= n;++j)
t.m[i][j] = 0;
//乘法运算
for(int i = 1;i <= n;++i)
for(int j = 1;j <= n;++j)
for(int k = 1;k <= n;++k)
t.m[i][j] = (t.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;
return t;
}
M M_Qpow(M a, LL b, int n)
{
M ret, base;
//初始化,根据快速幂中,ret = 1,ret初始化成单位矩阵
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= n;++j)
{
ret.m[i][j] = 0;
ret.m[i][i] = 1;
base.m[i][j] = a.m[i][j];
}
}
//注意矩阵乘法中a*b != b*a
while(b)
{
if(b & 1)
ret = mul(ret, base, n);
base = mul(base, base, n);
b >>= 1;
}
return ret;
}
int main()
{
M a, b;
b.m[1][1] = 1, b.m[1][2] = 1, b.m[2][1] = 1, b.m[2][2] = 0;
a.m[1][1] = 1, a.m[1][2] = 0;
LL n;
cin >> n;
M c = mul(a, M_Qpow(b, n - 1, 2), 2);
cout << c.m[1][1] << endl;
return 0;
}
矩阵快速幂--51nod-1242斐波那契数列的第N项的更多相关文章
- (矩阵快速幂)51NOD 1242斐波那契数列的第N项
斐波那契数列的定义如下: F(0) = 0 F(1) = 1 F(n) = F(n - 1) + F(n - 2) (n >= 2) (1, 1, 2, 3, 5, 8, 13, 21, ...
- 51nod 1242 斐波那契数列的第N项
之前一直没敢做矩阵一类的题目 其实还好吧 推荐看一下 : http://www.cnblogs.com/SYCstudio/p/7211050.html 但是后面的斐波那契 推导不是很懂 前面讲的挺 ...
- 51Nod 1242 斐波那契数列的第N项(矩阵快速幂)
#include <iostream> #include <algorithm> using namespace std; typedef long long LL; ; ; ...
- 51nod 1242 斐波那契数列的第N项——数学、矩阵快速幂
普通算法肯定T了,所以怎么算呢?和矩阵有啥关系呢? 打数学符号太费时,就手写了: 所以求Fib(n)就是求矩阵 | 1 1 |n-1 第一行第一列的元素. | 1 0 | 其实学过线代 ...
- 51 Nod 1242 斐波那契数列的第N项(矩阵快速幂模板题)
1242 斐波那契数列的第N项 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 斐波那契数列的定义如下: F(0) = 0 F(1) = 1 F(n) ...
- 1242 斐波那契数列的第N项
1242 斐波那契数列的第N项 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 斐波那契数列的定义如下: F(0) = 0 F(1) = 1 F(n) = F( ...
- 51Nod——T 1242 斐波那契数列的第N项
https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1242 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 ...
- python脚本10_打印斐波那契数列的第101项
#打印斐波那契数列的第101项 a = 1 b = 1 for count in range(99): a,b = b,a+b else: print(b) 方法2: #打印斐波那契数列的第101项 ...
- 51Nod - 1242 斐波那契(快速幂)
斐波那契数列的定义如下: F(0) = 0 F(1) = 1 F(n) = F(n - 1) + F(n - 2) (n >= 2) (1, 1, 2, 3, 5, 8, 13, 21, ...
随机推荐
- mybaits foreach
<select id="selectQuickConsultDoctorList" resultMap="BaseResultMap" parameter ...
- CVPR,ICCV和ECCV,计算机视觉三大顶级盛会
简介:https://blog.csdn.net/hualitlc/article/details/11099693 近几年ICCV,CVPR,和ECCV论文列表:https://www.xuebuy ...
- eclipse使用配置
eclipse设置工作空间为UTF-8(适应中文,避免乱码) windows---preference---general---workspace,修改textfile encoding eclips ...
- 【小梅哥FPGA进阶教程】MC8051软核在FPGA上的使用
十.MC8051软核在FPGA上的使用 本教程内容力求以详细的步骤和讲解让读者以最快的方式学会 MC8051 IP core 的应用以及相关设计软件的使用,并激起读者对 SOPC 技术的兴趣.本实验重 ...
- Java菜鸟之java基础语法,运算符(三)
赋值运算符 (一)JAVA种的赋值运算符 = ,代表代表的等于,一般的形式是 左边变量名称 = 右边的需要赋的指或者表达式,如果左侧的变量类型级别比较高,就把右侧的数据转换成左侧相同的高 ...
- opencv——(动态)旋转图像
#include "stdafx.h" #include <opencv2\opencv.hpp> #include <opencv\cv.h> #incl ...
- Android-获取网络图片设置壁纸
下载图片,设置壁纸 的代码: package liudeli.async; import android.app.Activity; import android.app.ProgressDialog ...
- window.open之postMessage传参数
这次要实现一个window.open打开子视窗的同时传参数到子视窗,关闭的时候返回参数. 当然简单的做法非常简单,直接在window.open的URL之后接参数即可,但是毕竟get method的参数 ...
- CDC--Demo
--CDC通过对事务日志的异步读取,记录DML操作的发生时间.--类型和实际影响的数据变化,然后将这些数据记录到启用--CDC时自动创建的表中.通过cdc相关的存储过程,可以获--取详细的数据变化情况 ...
- oracle 触发器序列号自增
步骤:1.创建表 table 2.创建序列 SEQUENCE 3.创建 触发器 截图实例: