征战蓝桥 —— 2014年第五届 —— C/C++A组第9题——斐波那契
题目
斐波那契数列大家都非常熟悉。它的定义是: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题——斐波那契相关推荐
- 征战蓝桥 —— 2014年第五届 —— C/C++A组第10题——波动数列
题目 观察这个数列: 1 3 0 2 -1 1 -2 ...这个数列中后一项总是比前一项增加2或者减少3.栋栋对这种数列很好奇,他想知道长度为 n 和为 s 而且后一项总是比前一项增加a或者减少b的整 ...
- 征战蓝桥 —— 2014年第五届 —— C/C++A组第5题——锦标赛
题目 如果要在n个数据中挑选出第一大和第二大的数据(要求输出数据所在位置和值),使用什么方法比较的次数最少? 我们可以从体育锦标赛中受到启发. 如图[1.png]所示,8个选手的锦标赛,先两两捉对比拼 ...
- 征战蓝桥 —— 2014年第五届 —— C/C++A组第6题——扑克排序
题目 A A 2 2 3 3 4 4, 一共4对扑克牌.请你把它们排成一行. 要求:两个A中间有1张牌,两个2之间有2张牌,两个3之间有3张牌,两个4之间有4张牌.请填写出所有符合要求的排列中,字典序 ...
- 征战蓝桥 —— 2014年第五届 —— C/C++A组第8题——地宫取宝
题目 X 国王有一个地宫宝库.是 n x m 个格子的矩阵.每个格子放一件宝贝.每个宝贝贴着价值标签.地宫的入口在左上角,出口在右下角.小明被带到地宫的入口,国王要求他只能向右或向下行走.走过某个格子 ...
- 征战蓝桥 —— 2014年第五届 —— C/C++A组第4题——史丰收速算
题目 史丰收速算法的革命性贡献是:从高位算起,预测进位.不需要九九表,彻底颠覆了传统手算!速算的核心基础是:1位数乘以多位数的乘法.其中,乘以7是最复杂的,就以它为例.因为,1/7 是个循环小数:0. ...
- 征战蓝桥 —— 2014年第五届 —— C/C++A组第3题——神奇算式
题目 由4个不同的数字,组成的一个乘法算式,它们的乘积仍然由这4个数字组成.比如: 210 x 6 = 1260 8 x 473 = 3784 27 x 81 = 2187 都符合要求.如果满足乘法交 ...
- 征战蓝桥 —— 2014年第五届 —— C/C++A组第1题——猜年龄
题目 小明带两个妹妹参加元宵灯会.别人问她们多大了,她们调皮地说:"我们俩的年龄之积是年龄之和的6倍". 小明又补充说:"她们可不是双胞胎,年龄差肯定也不超过8岁啊.&q ...
- 征战蓝桥 —— 2017年第八届 —— C/C++A组第5题——字母组串
题目 由 A,B,C 这3个字母就可以组成许多串. 比如:"A","AB","ABC","ABA","AACB ...
- 征战蓝桥 —— 2017年第八届 —— C/C++A组第6题——最大公共子串
题目 最大公共子串长度问题就是: 求两个串的所有子串中能够匹配上的最大长度是多少. 比如:"abcdkkk" 和 "baabcdadabc", 可以找到的最长的 ...
最新文章
- java数组中怎么去重_java数组去重怎么弄???大神来解
- WebSocket 集群解决方案
- hashlib 和loggin模块
- javacc的源码构建
- 您在2016年会做什么? Apache Spark,Kafka,Drill等
- VScode 常用快捷键
- java 与c des_Java和C/C++进行DES/AES密文传输
- F - 数据结构实验之栈与队列六:下一较大值(二)
- java xss 参数_JAVA 重写HttpServletRequest的获取参数防止xss攻击
- 为什么我在CSDN坚持写了3年多的博客?
- win10电脑虚拟网络设置方法
- GPS设备定位的经纬度偏移转换
- Opencv4学习-3、进阶图像基本操作1
- 【Docker学习笔记 二】Docker安装、运行流程与常用命令
- b站视频突破2倍方法,3倍?4倍?可以开10倍!!!
- 路飞学城结算中心实现
- 字节跳动校招面试题演练
- 通孔焊盘命名规范-002
- 【学习笔记】Python基础入门知识笔记,万字攻略带你走进Python编程
- 辗转相除法求最大公约数原理分析(附代码实现)
热门文章
- Android教程-Java基础2 语法与关系运算
- 一步一步学Silverlight 2系列(22):在Silverlight中如何用JavaScript调用.NET代码_转载...
- 一些常用的基本的liunx命令:
- ftl不存在为真_FreeMarker 处理不存在的变量
- 【数据结构总结】第七章 查找
- 永恒python怎么强化_永恒python加6_pythontip 挑战python (6-10)
- Java黑皮书课后题第5章:5.10(找出能被5和6整除的数)编写程序,显示从100到1000之间所有能被5和6整除的数,每行显示10个。数字之间用一个空格字符隔开
- 有序数组求中位数问题
- Java Class Loader Retrospect
- NYOJ--517--最小公倍数(大数打表)