[18/12/3]藍橋杯 練習系統 入門級別 Fibonacci數列求模問題 題解思路
阿新 • • 發佈:2018-12-03
前言略.
看到這個題目本來應該很高興的,因為什麼,因為太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 }
大概就是這樣了,歡迎批評指正,以及比我更高效的演算法方案在評論區討論!感謝觀看。