看到這表情包,突然想給自己出一道練習題

其實這個表情包也流傳了許久了,可我每次看到都覺得十分不可思議,為什么一定是163/326這對數(shù)字?毫無疑問,這是一對很特別的數(shù)字,消去相等的數(shù)位后,竟然得到了它們的最簡整數(shù)比。查了一下,這種現(xiàn)象叫做偶然對消。
我想知道還有沒有更多類似的數(shù)字。正好,最近在學數(shù)據(jù)結(jié)構(gòu),C語言雖然感覺挺不智能的,但還是得練,書上的題練多了心累,干脆就以找到類似的數(shù)字作為自定義地圖休息一下吧。
【目標】
尋找符合條件的十進制正整數(shù)a、b,滿足:消去相等的數(shù)位后做比,一定是它們的最簡整數(shù)比。
【代碼】
以實現(xiàn)功能為主,可讀性和效率都沒有經(jīng)過調(diào)整優(yōu)化。

主函數(shù)雙循環(huán),保證輸入算法的分子小于恒小于分母。函數(shù)HaveSimplerForm的返回值為布爾類型,返回該對正整數(shù)是否有相等的可消去數(shù)位,另使用一個布爾類型b來輸出是否滿足目標條件。如果滿足,輸出最簡整數(shù)比到x、y并打印結(jié)果。

實現(xiàn)算法的函數(shù)內(nèi)部也是用的雙循環(huán),內(nèi)層還有一次遞歸。大概思路就是判斷a的個位和b的個位是否相等,如果相等的話,把它們刪去個位后的數(shù)字輸入內(nèi)層遞歸,再調(diào)用一次;否則判斷a的個位和b的十位。重復直到遞歸返回值為false,說明已經(jīng)刪到只剩下一位了,不能刪了,這時判斷剩下的數(shù)字之比是否滿足最簡整數(shù)比,滿足的話把值輸出到e和f,否則輸出false的布爾型變量。
這里我自己額外設(shè)了一個比較苛刻的條件,即如果一對數(shù)字有多種可以消去的方法,例如1636/3236,分母消第一個3和第二個3得到的結(jié)果是不同的,那就要滿足任意一種消去方法都可以得到最簡整數(shù)比的結(jié)果。因此只要一個結(jié)果不對,輸出了false值,那么整個遞歸樹都可以直接返回了。另外要單獨判定,如果遞歸深度為0,即原始數(shù)據(jù)即將返回時,如果沒有進行過任何一次數(shù)位消去,直接輸出false,畢竟輸出默認為true,如果根本沒有辦法消去的一對數(shù)直接返回的話,根本沒有經(jīng)過最簡整數(shù)比的判斷,輸出還是true,這樣就不對了。

在實現(xiàn)算法的函數(shù)中還出現(xiàn)了一些自定義函數(shù)。其中求最大公約數(shù)的主要目的是求最簡整數(shù)比;后面的三個不用多說,在內(nèi)部的雙循環(huán)里有用到。
最后讓我們運行一下:

可以看到結(jié)果大致是正確的,并且可以驗證,感覺挺神奇。這里圖片顯示的是四位數(shù)的結(jié)果,前面我第一個函數(shù)寫的還是三位數(shù),忘改了。其實三位數(shù)以內(nèi)的結(jié)果一瞬間就能出來,四位數(shù)還是稍微慢了一點,大概要等個幾十秒鐘才能全部算完。
目前還有一個致命瑕疵,就是我沒法證明我的結(jié)果是沒有遺漏的,就這點破代碼寫寫改改也花了我三個多小時的時間,感覺自己挺廢的。不過得到結(jié)果的那一刻,真的是異常開心,所以還是決定把自己的經(jīng)歷分享出來,如果有人看的話,就當看個樂呵,順便拿走我的結(jié)果去多搞幾張表情包?