最考驗換位思考的一道演算法題

2021-09-11 08:58:44 字數 2901 閱讀 7542

最近在本站沸點上看到網友(@貓d)的一道數學題。仔細分析後,真心覺得那叫乙個難啊,腦子很容易枯竭。。。

題如下:

有兩個大於1的整數 x 和 y,甲知道二者的積,乙知道二者的和。

甲:我不知道這倆數是什麼!

乙:我不知道這倆數是什麼,我就知道你不知道!

甲:現在我知道了。

乙:我也知道了。

請問這兩個數是幾?

第一眼看去,什麼鬼?

想了好久,終於想明白了,本文準備用js解決它。

(手動分割線,確定馬上知道答案嗎?)

我們先看看正確答案:4 和 13。

我們驗證一下這個答案對不(只是驗證!),順便理解一下情境!

因為正確答案是 4 和 13,那麼甲知道的數字是52,甲又知道 52 可以寫成 2 * 26 或 4 * 13 這兩種可能。因此甲不知道這倆數具體是哪一種可能。

乙知道的數字是 17,但 17 的和式分解(我造的詞兒)可能有 2 + 15, 3 + 14,  4 + 13, 5 + 12,  6 + 11, 7+ 10 和 8 + 9 這幾種可能。此時關鍵的資訊來了,乙確信甲不知道答案。這是乙進行第一次換位思考, 思考的過程是這樣的:

假如答案是 2 和 15 的話,那麼甲知道的是 30,但 30 又可以分成 5 * 6 和 3 * 10,因此甲沒法確定答案。同理,乙驗證 3 和 14、4 和 13、5 和 12、6 和 11、7 和 10、8 和 9 等其餘可能,推理出甲沒法知道正確答案。因為它們的乘積的因式分解都不唯一。

因為此時乙已經告訴了甲,這乙個關鍵資訊,甲也可以反向推理了:

假如是 2 和 26 的話,那麼和是 28。而28的和式分解之一是 5 + 23,那麼乙會驗證 5 * 23的因式分解是否唯一,又因其恰好為倆素數,分解必然唯一。那麼乙就不會斷定我不知道答案了。因此 x 和 y 不能是 2 和 26,則是 4 和 13。到這裡,想必思路還很清晰吧。

乙一看甲竟然通過自己的話得到了答案,他進行了一次較複雜的推理,容我慢慢說來,可要仔細看好,沒講明白的話,多看兩遍,有點燒腦子,糊了!

此時,乙會站在甲的角度去想這個問題:

甲能得到正確答案,肯定是除了正確答案以外,排除掉了其他所有可能。排除條件就是:只有正確答案的和的和式分解的對應乘積的因式分解全不唯一這個條件是唯一的,即我之前告訴他的,「我就知道你不知道」。

比如,看 2 和 15 是否是答案嗎,其乘積是 30,而 30 的另乙個因式分解之一 5 * 6 的和是 11,並且 11 的所有和式分解 2 + 9,3 + 8,4 + 7,  5 + 6 的乘積因式分解也都不唯一。這樣的話,如果乘積真是30,到底 2 和15是正確答案呢,還是 5 和 6才是正確的答案呢,這樣甲沒法抉擇的。因此 2 和 15不是答案。同理驗證,除了 4 和 13 這一對兒外,其餘可能都不能使甲得出答案。

(上面只是驗證答案,下面我們要求出 4 和 13來。)

說到換位思考,要注意,這道題裡還有影之第三人,就是:「你」!

他倆最起碼,一人知道積是 52,另 一人知道和是 17。可我們讀者呢,那是倆眼一抹黑啊,可不知道二人知道的數字。讀者掌握得資訊要比他二人少,所以要想得正確答案難度倍增。

我們的換位思考就是想法依次從甲乙的話裡,去過濾出正確答案。

終於要寫**啦!!!

我們不妨假設 x <= y。為了減少計算量,二者都小於 100 吧。

首先我們先算 x 和 y 的所有可能:

const max = 100;

let sums = {};

let products = {};

for (var i = 2; i < max; i++) );

let s = x + y;

sums[s] = sums[s] || ;

sums[s].push();

}}複製**

products 是所有數的乘積的因式分解集合。比如 products[12] 的值是 [, ]。類似,sums 是所有數的和式分解。

甲:我不知道答案。
對應這句話,我們要在 products 中過濾掉因式分解唯一的情況:

for (let key in products) 

}複製**

乙:我不知道答案,
同理,我們也要在 sums 中過濾掉和式分解唯一的情況:

for (let key in sums) 

}複製**

乙:我就知道你不知道!
對於任意一可能和值,其每種和式分解對應的乘積都該有多種可能分解形式。我們過濾掉 sums 中不滿足的情形:

for (let key in sums) );

if (!flag)

}複製**

甲:現在我知道了。

乙:我也知道了。

根據乙最後換位思考的過程,我們遍歷sums的每乙個key。再根據排除條件,即,和式分解對應的積的因式分解是否唯一,來確定可能的結果。

for (let key in sums) )

if (r.length == 1)

return

false

});if (r.length == 1)

}複製**

寫到這裡,算是完事了,也不知道我寫明白了沒有。。。確實有點繞,算得也比較笨。。

另外,**還有點小問題,ps.filter 是取巧做的。算是求出了 4 和 13 這兩個值了。當然,只限於小於100的數,也只是驗證了存在性。唯一性恐怕需要數學去證明了,哥德**猜想?

寫此文的過程,想起了當年看博弈論時的情景,腦仁兒疼!

最後給出完整demo位址。

一道演算法題,引發的思考

引言 有人問我這樣乙個問題,希望寫出 實現 有p0,p1兩點座標,組成乙個線段,求此線段與x點的的距離 我並不知道,如何完全的實現此功能,因為求點與線的公式,我記得是高中知識,但是我已經忘得差不多了,只是知道勾股定理算兩點間距離,直線方程有個斜率,如果給我時間去細想的話,應該可以理出頭緒,得到個寫此...

一道演算法題

兩個燒杯,乙個放糖乙個放鹽,用勺子舀一勺糖到鹽,攪拌均勻,然後舀一勺混合 物會放糖的燒杯,問你兩個燒杯哪個雜質多?一樣多吧 對的 為啥?是不是因為 糖和鹽本來就是均勻的 因為,就算不攪拌均,你放一勺過去,那邊放一勺不含雜質的過來,那麼都是一勺雜之 如果攪拌均勻的話也是一樣 小依 21 45 32 也...

一道演算法題

1.上午主要做了對翻譯任務的劃分,下午把 翻譯完畢。2.明天要講的演算法題 對乙個集合,求出其連續元素組成的子集中,和最大的子集 我對這道題的理解是 1 若集合中最小值大於0,意味著所有的都大於0,則最大的子集和,為所有值加起來 2 若集合中最大值小於0,意味著所有的都小於0,則最大的子集和,為集合...