文章目錄
- 1.問題描述
- 2.問題描述
- 3.思路分析
- 4.代碼分析
1.問題描述
這個是我很久之前寫的一個題目,當時研究了這個題目好久,發布了一篇題解,后來很多人點贊,我都沒有意識到這個問題的嚴重性,我甚至都在懷疑自己:我寫的題解這么優秀嗎?
臨近藍橋杯,最近也是在研究這個藍橋杯的真題嘛,這個題目實際上就是真題,但是當時我并不知道,現在回頭去看這個去年的11月份我寫下來的對應的題解,也讓我想了好久,才發現了這個規律,所以今天記錄下來
下面的這個是大家的評論,這個方法絕對是很巧妙的,但是不容易想到,我也忘記了自己當時是怎么想到的:
2.問題描述
上面的這個圖片里面已經把這個題目的問題描述的很清楚了,我覺得,實際上,下面的這個數列的結果基本上就是后面的一項等于前面的三項的和;
前面的幾個數據其實就是我們的這個數的每一個數位上面的數字,例如這個197,他的每一個數位上面的數據組成了我們的下面的數列里面的前面的三個數據;
17就是前面的三個數字的求和,33就是他前面的三個數字的求和以此類推下去,發現找到了這個197,因此這個197就是一個類斐波那契數;
他需要我們求接的就是這個0-10000000里面的這個最大的斐波那契數;
3.思路分析
因為這個在去年的藍橋杯的省賽里面是一個填空題,相較于這個編程題,其實這類題目是容易拿分的,我覺得,但是這個題目因為給定的這個數據范圍比較大嗎,所以這個其實如果我當時在考場上面,可能做不出來這個題目;
下面說一下我的這個思路,每一項是前面的幾個項求和,這個規律很好找,但是如果要是真正的無腦進行計算,這個其實計算量是蠻大的,因此不妨看一下我下面的這個思路:
使用這個197作為例子把,實際上我們規定一個數組:
初始情況下這個數組里面的元素就是:[1,9,7];
這個時候我們計算一下前面的幾個數據的求和,加入到數組里面去:[1,9,7,17];
接下來就是去掉數組里面的第一個數據,最后一個數據*2減去第一個新的數據:
1)首先去掉數組里面的第一個數據就是1,9,7,17
2)乘上二減去第一個元素就是17*2-1=33,這個元素就是我們的新的元素;
3)去掉第一個元素,更新之后的這個數組就是[9,7,17,33];
4)乘上2減去第一個新的元素:33乘上2=66,減去第一個新元素9=57,和上面的例子是一樣的;
5)這個時候的數組就是9,7,17,33,57,去掉第一個元素就是7,17,33,57;
6)57*2-7==107符合上面的這個情況;
7)綜上所述,大家是可以發現,這個實際上就是乘上2減去數組里面的第一個元素,這個數值添加到我們的數組里面去,然后就是去掉數組里面的第一個元素,以此類推,一直進行下去;
8)這個方法不能說非常的高明,但是比這一項等于前面的三項的數據求和的這個方法更好一些把,我覺得更容易實現一些;
4.代碼分析
1)下面的這個就是我當時發布題解的時候的代碼,里面是有一部分注釋的,但是可能杰士德不是很清楚,因此我再次說明一下
2)首先需要關注的就是這個里面的main方法,確定這個篩選的范圍,pd就是我們的自定義的方法,返回值是布爾值,如果是真的,這個時候就會被打印輸出,假的的話an=0保持初始數值;
3)pd方法里面,首先是對于這個傳進來的參數進行拆解,分成不同的數位上面的數據;
4)anss就是把拆解之后的每一個數位上面的數據求和,添加到我們的這個數組里面去;
5)*2-ans.get(0)就是上面的這個思路分析里面的乘上2減去這個數組里面的第一個元素,粑粑這個數據添加到我們的數組里面去
6)remove方法把我們的數組里面的第一個數據溢移除,和上面的這個思路里面的做法是一致的;
7)其實這個先添加還是先刪除的這個順序是沒有影響的;
8)因為這個是一個循環嗎,所以如果可以找到,就會跳出來,超過了這個i這個數值還是沒有找到,說明這個數據就是不符合條件的,我們也會從這個循環里面跳出來;
import java.util.ArrayList;
import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);long an=0;for(int i=197;i<1e7;i++){if(pd(i)){an=i;}}System.out.println(an);}private static boolean pd(int i){ArrayList<Integer> ans = new ArrayList<>();String s=""+i;int anss=0;//轉換為這個string方便獲取每一個數位上面的證書for(int j=0;j<s.length();j++){//下面的這個ans就是我們的列表容器ans.add(s.charAt(j)-'0');anss=anss+s.charAt(j)-'0';}//上面的這個循環究竟是在干什么事情:下面的這個以1234為例子說明,方便理解//列表 ans 存儲了整數 1234 的各個數位數字 [1, 2, 3, 4],// 變量 anss 的值為 10,即整數 1234 各個數位數字的總和。ans.add(anss);//這個時候i的數組元素就是ans[1,2,3,4,10]while(true){//乘以2減去這個里面的第一個元素就是這個類斐波那契數列的規律,避免使用純粹的數學方法計算anss=(anss*2)-ans.get(0);ans.remove(0);ans.add(anss);if(anss==i){return true;}else if(anss>i){return false;}}}
}