标题:斐波那契

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

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 &amp;&amp; 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. Netty学习五:Buffers

    1. Netty中的缓冲 在Netty中并没有使用Java自带的ByteBuffer,而是自己实现提供了一个缓存区来用于标识一个字节序列,并帮助用户操作原始字节或者自定义的POJO. Java NIO ...

  2. Raspberry Pi B+ 定时向物联网yeelink上传CPU GPU温度

     Raspberry Pi B+ 定时向物联网yeelink上传CPU GPU温度 硬件平台: Raspberry Pi B+ 软件平台: Raspberry 系统与前期安装请参见:树莓派(Ros ...

  3. 动作之CCActionInstant(立即动作)家族

    立即动作就是不需要时间,马上就完成的动作.立即动作的共同基类是CCActionInstant.CCActionInstant的常用子类有: CCCallFunc:回调函数包装器 CCFlipX:X轴翻 ...

  4. (转)实战p12文件转pem文件

    需要实现这个功能的一般都是app开发证书不支持通配符(即com.xxx.xxx.xxx格式),在业务需求上类似消息推送这样的业务. 1.首先生成一个ssl的证书 选择app IDS 后实现下面这个(这 ...

  5. PHP 7.1 新特性

    PHP 7.1 新特性 1.密集阵算法 2.php int64位支持(2GB的字符串和2GB的文件的上传) 3.$a<=>$b  操作符,排序时有用 4.标量的支持,如果声明int传入st ...

  6. selenim之ActionChains(一)

    大家好,来介绍下,今天要分享的是小编学ActionChains的经验. 先来说一下今天要用到的方法: click(element=null)                               ...

  7. Win10安装LoadRunner11

    一.下载 地址:http://www.51testing.com/?uid-4827-action-viewspace-itemid-225451 二.安装 本来想写,结果和别人的一样就不写了:htt ...

  8. TypeScript 版本相关

    TypeScript 1.3 元组类型 // Declare a tuple type var x: [string, number]; // 初始化 x = []; // ok // 错误的初始化 ...

  9. Storm中重要对象的生命周期

    Spout方法调用顺势 declareOutputFields()(调用一次) open() (调用一次) activate() (调用一次) nextTuple() (循环调用 ) deactiva ...

  10. python3中报错AttributeError: module &#39;sys&#39; has no attribute &#39;setdefaultencoding&#39;

    reload(sys) sys.setdefaultencoding("utf-8") f = open('.\\24.novel.txt','rb') str = f.read( ...