标题:斐波那契

斐波那契数列大家都非常熟悉。它的定义是:

f(x) = 1                    .... (x=1,2)
f(x) = f(x-1) + f(x-2) .... (x>2) 对于给定的整数 n 和 m,我们希望求出:
f(1) + f(2) + ... + f(n) 的值。但这个值可能非常大,所以我们把它对 f(m) 取模。
公式参见【图1.png】 但这个数字依然很大,所以需要再对 mod 求模。

【数据格式】

输入为一行用空格分开的整数 n m mod (0 < n, m, mod < 10^18)

输出为1个整数

例如,如果输入:

2 3 5

程序应该输出:

0

再例如,输入:

15 11 29

程序应该输出:

25

资源约定:

峰值内存消耗 < 256M

CPU消耗 < 1000ms

Σf(n)=f(n+2)-1

尽量用迭代

规模很大,数据很大

简单解法,直接计算斐波那契数列 能得一部分分数

void solve1() {
LL a = 1;
LL b = 1;
//直接计算斐波那契数列 能得一部份分
if (m >= n + 2) {
for (LL i = 3; i <= n + 2; ++i) {
LL t = a;
a = b;
b += t;
}
printf("%llu\n", b % mod - 1);
} else {//m<n+2
LL fibM, fibN_2 = 0;
for (LL i = 3; i <= n + 2; ++i) {
LL t = a;
a = b;
b += t;
if (i == m) fibM = b;
}
fibN_2 = b;
printf("%llu %llu\n", fibN_2, fibN_2 % fibM % mod - 1);
}
}

斐波那契数列可以用矩阵运算解出来

快速斐波那契<--矩阵运算<--快速矩阵幂运算(logn时间复杂度)

mod带入到矩阵乘法中,每次乘和每次加,都对结果进行模运算->运算数在LL的范围内

整数快速乘法,并在乘法中加入模运算

#include <iostream>
#include <algorithm>
#include <cstring> using namespace std; typedef unsigned long long LL; LL n, m, mod; class M {
public:
LL data[2][2]; M() { memset(data, 0, sizeof(data)); }
}; //将两个2*2的矩阵相乘
M *mul(M *m1, M *m2) {
M *ans = new M();
ans->data[0][0] = m1->data[0][0] * m2->data[0][0] + m1->data[0][1] * m2->data[1][0];
ans->data[0][1] = m1->data[0][0] * m2->data[0][1] + m1->data[0][1] * m2->data[1][1];
ans->data[1][0] = m1->data[1][0] * m2->data[0][0] + m1->data[1][1] * m2->data[1][0];
ans->data[1][1] = m1->data[1][0] * m2->data[0][1] + m1->data[1][1] * m2->data[1][1];
return ans;
} //快速乘法
LL mm(LL a, LL b, LL mod) {
if (a > b) {
LL t = a;
a = b;
b = t;
}
LL x = 0;
while (b != 0) {
if ((b & 1) == 1) {
x = (x + a) % mod;
}
a = (a * 2) % mod;
b >>= 1;
}
return x;
} //将两个2*2的矩阵相乘
M *mul(M *m1, M *m2, LL mod) {
M *ans = new M();
ans->data[0][0] = (mm(m1->data[0][0], m2->data[0][0], mod) + mm(m1->data[0][1], m2->data[1][0], mod)) % mod;
ans->data[0][1] = (mm(m1->data[0][0], m2->data[0][1], mod) + mm(m1->data[0][1], m2->data[1][1], mod)) % mod;
ans->data[1][0] = (mm(m1->data[1][0], m2->data[0][0], mod) + mm(m1->data[1][1], m2->data[1][0], mod)) % mod;
ans->data[1][1] = (mm(m1->data[1][0], m2->data[0][1], mod) + mm(m1->data[1][1], m2->data[1][1], mod)) % mod;
return ans;
} //m的n次幂log(n)
M *mPow(M *m, LL n) {
M *E = new M();//单位矩阵
E->data[0][0] = 1;
E->data[1][1] = 1; while (n != 0) {
if (n & 1 == 1) {
E = mul(E, m);
}
m = mul(m, m);//按平方倍增
n >>= 1;
}
return E;
} //m的n次幂log(n) 并去模
M *mPow(M *m, LL n, LL mod) {
M *E = new M();//单位矩阵
E->data[0][0] = 1;
E->data[1][1] = 1; while (n != 0) {
if ((n & 1) == 1) {
E = mul(E, m, mod);
}
m = mul(m, m, mod);//按平方倍增
n >>= 1;
}
return E;
} //求斐波那契数列
LL fib(LL i) {
//[1,1]B^(i-2)
M *A = new M();
A->data[0][0] = 1;
A->data[0][1] = 1;
M *B = new M();
B->data[0][0] = 1;
B->data[0][1] = 1;
B->data[1][0] = 1;
M *ans = mul(A, mPow(B, i - 2));
return ans->data[0][0];
} //求斐波那契数列并取模
LL fib(LL i, LL mod) {
//[1,1]B^(i-2)
M *A = new M();
A->data[0][0] = 1;
A->data[0][1] = 1;
M *B = new M();
B->data[0][0] = 1;
B->data[0][1] = 1;
B->data[1][0] = 1;
M *ans = mul(A, mPow(B, i - 2, mod), mod);
return ans->data[0][0];
} void solve2() {
if (m >= n + 2) {
printf("%llu\n", fib(n + 2, mod) - 1);
} else {//m<n+2
LL fibm = fib(m);
printf("%llu\n", fib(n + 2, fibm) % mod - 1);
}
} int main(int argc, const char *argv[]) {
scanf("%llu %llu %llu", &n, &m, &mod);
solve2();
return 0;
}

数论+矩阵快速幂|斐波那契|2014年蓝桥杯A组9-fishers的更多相关文章

  1. 洛谷- P1306 斐波那契公约数 - 矩阵快速幂 斐波那契性质

    P1306 斐波那契公约数:https://www.luogu.org/problemnew/show/P1306 这道题目就是求第n项和第m项的斐波那契数字,然后让这两个数求GCD,输出答案的后8位 ...

  2. POJ 3070 Fibonacci矩阵快速幂 --斐波那契

    题意: 求出斐波那契数列的第n项的后四位数字 思路:f[n]=f[n-1]+f[n-2]递推可得二阶行列式,求第n项则是这个矩阵的n次幂,所以有矩阵快速幂模板,二阶行列式相乘, sum[ i ] [ ...

  3. [P1306] 斐波那契公约数 (矩阵快速幂+斐波那契数列)

    一开始数据没加强,一个简单的程序可以拿过 gcd(f[n],f[m])=f[gcd(n,m)] 下面这个是加强数据之后的80分代码 #include<bits/stdc++.h> usin ...

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

    [题目描述] 我们知道斐波那契数列0 1 1 2 3 5 8 13…… 数列中的第i位为第i-1位和第i-2位的和(规定第0位为0,第一位为1). 求斐波那契数列中的第n位mod 10000的值. [ ...

  5. SPOJ 5152 Brute-force Algorithm EXTREME && HDU 3221 Brute-force Algorithm 快速幂,快速求斐波那契数列,欧拉函数,同余 难度:1

    5152. Brute-force Algorithm EXTREME Problem code: BFALG Please click here to download a PDF version ...

  6. HDU 2256 Problem of Precision 数论矩阵快速幂

    题目要求求出(√2+√3)2n的整数部分再mod 1024. (√2+√3)2n=(5+2√6)n 如果直接计算,用double存值,当n很大的时候,精度损失会变大,无法得到想要的结果. 我们发现(5 ...

  7. 剑指offer——矩阵覆盖(斐波那契变形)

    ****感觉都可以针对斐波那契写一个变形题目的集合了****** 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? cl ...

  8. HDU 1568 快速求斐波那契前四位

    思路: 把斐波那契通项公式转化成log的形式,高中数学... //By SiriusRen #include <bits/stdc++.h> using namespace std; ], ...

  9. 数学算法(一):快速求斐波那契数第n项通过黄金分割率公式

    有一个固定的数学公式= =,不知道的话显然没法应用 首先黄金分割率接近于这个公式, (以下为黄金分割率与斐波那契的关系,可跳过) 通过斐波那契数列公式 两边同时除以 得: (1) 注意后一项比前一项接 ...

随机推荐

  1. Git SSH密钥对生成以及多个SSH存在情况配置

    一.使用Git Bash 生成一个新的SSH密钥 1. 打开 Git Bash. 2. 邮箱设置粘贴下面的文字,替换成为你自己的邮箱. Github SSH 1 $ ssh-keygen -t rsa ...

  2. Unity shader学习之逐像素漫反射光照模型

    shader如下: Shader "Custom/Diffuse Fragment-Level" { Properties { _Diffuse (,,,) } SubShader ...

  3. 扩展kmp 模板

    算法可以参考http://wenku.baidu.com/view/8e9ebefb0242a8956bece4b3.html 百度文库 #include<iostream> #inclu ...

  4. scu 4444 Travel

    题意: 一个完全图,有n个点,其中m条边是权值为a的无向边,其它是权值为b的无向边,问从1到n的最短路. 思路: 首先判断1和n被哪种边连通. 如果是被a连通,那么就需要全部走b的边到达n,选择最小的 ...

  5. oracle查询每隔5分钟区间内的数据量

    SELECT COUNT (DISTINCT tmp.PLATE) totalNum, tmp.newTime FROM ( SELECT T .LICENSE_PLATE plate, TO_CHA ...

  6. QT构建窗体(父窗体传为野指针)异常案例

    [1]源码 工作中,时常会遇到各种各样的异常场景,有些异常场景很常见,必要备录,以防再犯. 分享本案例为:QT创建窗体时parent父窗体传野指针引起异常. 本案例源码如下: 1.1 默认新建一个QT ...

  7. memcache、redis、mongoDB 如何选择?

    不同的 Nosql,其实应用的场景各有不同,所以我们应该先了解不同Nosql 之间的差别,然后分析什么才是最适合我使用的 Nosql. Nosql 介绍 Nosql 的全称是 Not Only Sql ...

  8. python将一个列表的元素随机打乱

    java可以用Collections.shuffle(List)来实现,python怎么实现呢? python要利用random模块的shuffle方法 代码如下: import random x = ...

  9. DBUtils (30)

    DBUtils是java编程中的数据库操作实用工具,小巧简单实用. DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码. Dbutils三个核心功能介绍 一.  QueryRunn ...

  10. Linux基础命令---检查密码文件pwck

    pwck 检查用户密码文件“/etc/passwd”和“/etc/shadow”的完整性,将验证结果送到标砖输出.提示用户删除格式不正确或有其他不可更正错误的条目.检查以验证每个条目是否具有:正确的字 ...