题目

斐波那契数列大家都非常熟悉。它的定义是: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

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include < xxx>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

代码

#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)); }
};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+2LL 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);}}//将两个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+2LL 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);
//    solve1();
//    for (int i = 3; i <= 10; ++i) {//       cout<< fib(i)<<endl;
//    }solve2();
//cout<<mm(3,7,5);return 0;
}

征战蓝桥 —— 2014年第五届 —— C/C++A组第9题——斐波那契相关推荐

  1. 征战蓝桥 —— 2014年第五届 —— C/C++A组第10题——波动数列

    题目 观察这个数列: 1 3 0 2 -1 1 -2 ...这个数列中后一项总是比前一项增加2或者减少3.栋栋对这种数列很好奇,他想知道长度为 n 和为 s 而且后一项总是比前一项增加a或者减少b的整 ...

  2. 征战蓝桥 —— 2014年第五届 —— C/C++A组第5题——锦标赛

    题目 如果要在n个数据中挑选出第一大和第二大的数据(要求输出数据所在位置和值),使用什么方法比较的次数最少? 我们可以从体育锦标赛中受到启发. 如图[1.png]所示,8个选手的锦标赛,先两两捉对比拼 ...

  3. 征战蓝桥 —— 2014年第五届 —— C/C++A组第6题——扑克排序

    题目 A A 2 2 3 3 4 4, 一共4对扑克牌.请你把它们排成一行. 要求:两个A中间有1张牌,两个2之间有2张牌,两个3之间有3张牌,两个4之间有4张牌.请填写出所有符合要求的排列中,字典序 ...

  4. 征战蓝桥 —— 2014年第五届 —— C/C++A组第8题——地宫取宝

    题目 X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签.地宫的入口在左上角,出口在右下角.小明被带到地宫的入口,国王要求他只能向右或向下行走.走过某个格子 ...

  5. 征战蓝桥 —— 2014年第五届 —— C/C++A组第4题——史丰收速算

    题目 史丰收速算法的革命性贡献是:从高位算起,预测进位.不需要九九表,彻底颠覆了传统手算!速算的核心基础是:1位数乘以多位数的乘法.其中,乘以7是最复杂的,就以它为例.因为,1/7 是个循环小数:0. ...

  6. 征战蓝桥 —— 2014年第五届 —— C/C++A组第3题——神奇算式

    题目 由4个不同的数字,组成的一个乘法算式,它们的乘积仍然由这4个数字组成.比如: 210 x 6 = 1260 8 x 473 = 3784 27 x 81 = 2187 都符合要求.如果满足乘法交 ...

  7. 征战蓝桥 —— 2014年第五届 —— C/C++A组第1题——猜年龄

    题目 小明带两个妹妹参加元宵灯会.别人问她们多大了,她们调皮地说:"我们俩的年龄之积是年龄之和的6倍". 小明又补充说:"她们可不是双胞胎,年龄差肯定也不超过8岁啊.&q ...

  8. 征战蓝桥 —— 2017年第八届 —— C/C++A组第5题——字母组串

    题目 由 A,B,C 这3个字母就可以组成许多串. 比如:"A","AB","ABC","ABA","AACB ...

  9. 征战蓝桥 —— 2017年第八届 —— C/C++A组第6题——最大公共子串

    题目 最大公共子串长度问题就是: 求两个串的所有子串中能够匹配上的最大长度是多少. 比如:"abcdkkk" 和 "baabcdadabc", 可以找到的最长的 ...

最新文章

  1. java数组中怎么去重_java数组去重怎么弄???大神来解
  2. WebSocket 集群解决方案
  3. hashlib 和loggin模块
  4. javacc的源码构建
  5. 您在2016年会做什么? Apache Spark,Kafka,Drill等
  6. VScode 常用快捷键
  7. java 与c des_Java和C/C++进行DES/AES密文传输
  8. F - 数据结构实验之栈与队列六:下一较大值(二)
  9. java xss 参数_JAVA 重写HttpServletRequest的获取参数防止xss攻击
  10. 为什么我在CSDN坚持写了3年多的博客?
  11. win10电脑虚拟网络设置方法
  12. GPS设备定位的经纬度偏移转换
  13. Opencv4学习-3、进阶图像基本操作1
  14. 【Docker学习笔记 二】Docker安装、运行流程与常用命令
  15. b站视频突破2倍方法,3倍?4倍?可以开10倍!!!
  16. 路飞学城结算中心实现
  17. 字节跳动校招面试题演练
  18. 通孔焊盘命名规范-002
  19. 【学习笔记】Python基础入门知识笔记,万字攻略带你走进Python编程
  20. 辗转相除法求最大公约数原理分析(附代码实现)

热门文章

  1. Android教程-Java基础2 语法与关系运算
  2. 一步一步学Silverlight 2系列(22):在Silverlight中如何用JavaScript调用.NET代码_转载...
  3. 一些常用的基本的liunx命令:
  4. ftl不存在为真_FreeMarker 处理不存在的变量
  5. 【数据结构总结】第七章 查找
  6. 永恒python怎么强化_永恒python加6_pythontip 挑战python (6-10)
  7. Java黑皮书课后题第5章:5.10(找出能被5和6整除的数)编写程序,显示从100到1000之间所有能被5和6整除的数,每行显示10个。数字之间用一个空格字符隔开
  8. 有序数组求中位数问题
  9. Java Class Loader Retrospect
  10. NYOJ--517--最小公倍数(大数打表)