前言略.
看到这个题目本来应该很高兴的,因为什么,因为太TM的基础了啊!
可是当你用常规方法尝试提交OJ时你会发现..hhh...运行超时..(开心地摇起了呆毛
1 //Fibonacci数列递归一般问题常规方法(当目标序列号<32时适用 评判标准:运行时间<1.00s) 2 #include <iostream> 3 using namespace std; 4 5 long Fib(int); 6 7 int main() 8 { 9 10 int n = 0; cin >> n; 11 cout << Fib(n) % 10007; 12 return 0; 13 } 14 15 long Fib(int x) 16 { 17 if (x != 0) 18 { 19 if (x == 1 || x == 2) 20 { 21 return 1; 22 } 23 else return (Fib(x - 1) % 10007 + Fib(x - 2) % 10007) % 10007; 24 } 25 }
这里顺带提一下,大数求模的一个运算律(只列了一个):
(a+b)%N == a%N+b%N == (a%N+b%N)%N,常用哦~
于是我想,这样用原来的常规方法内存又要占爆,CPU又要发烧(毕竟n值一上去那个递归次数你懂得.)
于是转变思路用循环多次填充的方法尝试再(wan)次(quan)实(chong)现(xie)了一遍代码,以10位Fibonacci数的顺序生成为一轮填充
剩下的只需要找到目标n值对应的10位中的序列号以及循环填充轮数就行了,省省宝贵的内存(虽然限制是256M但是总觉得是虚报的...)
下面是具体实现方案,记得打注释部分要写,不然就会在循环填充的时候卡死。
1 //Fibonacci数列对数求模问题 题解 来源:蓝桥杯训练系统入门级 作者:Yuudachi晚风 2 3 #include <iostream> 4 using std::cin; 5 using std::cout; 6 7 int main() 8 { 9 10 int n = 0; cin >> n; 11 12 int Fibs[10] = {}; //10个一轮进行循环填充,可以自行调试更改 13 Fibs[0] = Fibs[1] = 1; 14 int seq = n % 10 - 1; //目标输出数组中目标数值序列号 15 if (seq == -1) seq = 9; //重置10的倍数的序列值 16 long times = n / 10 + 1; //打到目标输出数组所需轮数 17 if (n % 10 == 0) times = n / 10; //重置10的倍数的循环填充轮数值 18 19 //cout << "seq=" << seq << "times=" << times << endl; 20 21 for (int i = 0; i < times; i++) 22 { 23 for (long j = 2; j < 10; j++) 24 { 25 if (i != 0 && j == 2) 26 { 27 Fibs[0] = Fibs[8] + Fibs[9]; //第一轮填充后每轮重置序列0的值 28 Fibs[1] = Fibs[9] + Fibs[0]; //第一轮填充后每轮重置序列1的值 29 } 30 Fibs[j] = (Fibs[j - 1] + Fibs[j - 2]) % 10007; 31 } 32 } 33 cout << Fibs[seq] % 10007; 34 35 return 0; 36 }
大概就是这样了,欢迎批评指正,以及比我更高效的算法方案在评论区讨论!感谢观看。
内容来源于网络如有侵权请私信删除
- 还没有人评论,欢迎说说您的想法!