用SQL解決兩道有趣的題(二)

yangtingkun發表於2008-01-03

OracleSQL語句功能還是很強的,看到兩道比較有趣的題,用SQL來嘗試求解。

SQL解決兩道有趣的題(一):http://yangtingkun.itpub.net/post/468/448940

 

 

第二個問題:

GaussPoincare在天堂相遇了,上帝說:你們都是人間最偉大的數學家,那我來出道題考考你們誰更聰明。我在左手寫一個大於1小於100的數,在右手同樣寫一個大於1小於100的數,然後把他們的和寫在Gauss手上,把積寫在Poincare手上,看看你們能不能猜出這兩個數字是幾。
Gauss
看了手上的數字,說:我不知道這兩個數字是幾,可我保證Poincare也不知道。
Poincare
看了手上的數字,說:我原來的確不知道那兩個數字是幾,可我現在知道了。

Gauss
說:那我也知道了。

問題:那兩個數字是幾?

粗看上去似乎和剛才第一題很像,如果仔細研究就會發現二者的區別還是很大的,相比之下,這道題比第一題要難一些。

仍然是先給出SQL解,然後描述一下思路:

SQL> WITH T_NUM AS
  2  (SELECT ROWNUM + 1 NUM FROM DUAL CONNECT BY LEVEL < 99)
  3  SELECT A, B
  4  FROM
  5  (
  6   SELECT
  7    A,
  8    B,
  9    TOTAL,
 10    MUL,
 11    MUL_P,
 12    COUNT(DECODE(MUL_P, 1, 1)) OVER(PARTITION BY TOTAL) VALUE
 13   FROM
 14   (
 15    SELECT
 16     A,
 17     B,
 18     TOTAL,
 19     MUL,
 20     COUNT(*) OVER (PARTITION BY TOTAL) TOTAL_P,
 21     COUNT(*) OVER (PARTITION BY MUL) MUL_P
 22    FROM
 23    (
 24     SELECT
 25      A,
 26      B,
 27      TOTAL,
 28      MUL,
 29      MIN(MUL_P) OVER (PARTITION BY TOTAL) MUL_M
 30     FROM
 31     (
 32      SELECT
 33       A.NUM A,
 34       B.NUM B,
 35       A.NUM + B.NUM TOTAL,
 36       A.NUM * B.NUM MUL,
 37       COUNT(*) OVER (PARTITION BY A.NUM + B.NUM) TOTAL_P,
 38       COUNT(*) OVER (PARTITION BY A.NUM * B.NUM) MUL_P 
 39      FROM T_NUM A, T_NUM B
 40      WHERE A.NUM < B.NUM
 41     )
 42    ) 
 43    WHERE MUL_M != 1
 44   )
 45  )
 46  WHERE MUL_P = 1
 47  AND VALUE = 1;

         A          B
---------- ----------
         4         13

下面簡單描述一下思路:

WITH語句就是構造一張基礎資料表。

最內層的迴圈構造兩個數的笛卡兒積,列出所有的可能,不過對於我們來說,A1B2A2B1沒有區別,因此加上限制條件A > B。迴圈中的分析函式用來計算AB兩個數的和相同的個數以及AB兩個數的積相同的個數。

下面到了這道題和第一題的區別之處。Gauss不但自己不知道,還可以確認Poincare也不知道。這說明AB兩個數構成Gauss手裡的和TATOL不但不是唯一的,而且所有能構成這個TOTALAB的積MUL都不是唯一的。這就是第二層巢狀的含義。

到了第三層,過濾掉上面那些不符合條件的AB之後。要解決的問題就是Poincare知道AB的答案後,Gauss也知道了。

這說明對於TOTAL這個值,所有AB的組合中有一個且只有一個組合它們的乘積是唯一確定的。這是透過第四層巢狀中那個COUNT(DECODE) OVER實現的。

最後過濾乘積唯一,且對於相同TOTAL的所有AB組合中有且僅有一個乘積唯一確定的AB組合。

如果還是不明白,可以將這個巢狀一層層執行,觀察每一步的執行結果,有助於理解每一步實現的目的。

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-83501/,如需轉載,請註明出處,否則將追究法律責任。

相關文章