1. 程式人生 > >[18/12/3]藍橋杯 練習系統 入門級別 Fibonacci數列求模問題 題解思路

[18/12/3]藍橋杯 練習系統 入門級別 Fibonacci數列求模問題 題解思路

前言略.

看到這個題目本來應該很高興的,因為什麼,因為太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 }

大概就是這樣了,歡迎批評指正,以及比我更高效的演算法方案在評論區討論!感謝觀看。