阿里校招筆試的一道邏輯題


最近在@研究者July 的微博上看到一道有趣的邏輯題,是阿里巴巴2016年校招筆試題,原微博地址如下:http://weibo.com/1580904460/CyEfEyOT6?type=comment#_rnd1441345987133 。順便說一下,讀書的時候@研究者July的博客我也是經常看的,學到不少東西。在這里把這道題搬過來,並給出自己的解法。

是一道選擇題,原題如下:

1, 2, 3, …… , 49, 50里選擇一個集合S,使得若x屬於S,則2x不屬於S,則S最多能有()個元素。

A. 25    B. 27     C. 30     D. 33     E. 36     F. 37

 

這道題如果直接暴力求解也可以很快得到答案,本文想給出一個一般化的解法。

假設最大的數不是50,而是n。根據題意,我們只需將1到n之間所有有2倍關系的數連接起來構造一個“二倍鏈”,因為不同的二倍鏈之間不會相互干擾,所以可以單獨考慮每個二倍鏈最多能取多少個數,然后將所有二倍鏈可取的數目加起來即可。

比如n=11,那么所有的二倍鏈有:

1--2--4--8

3--6

5--10

7

9

11

我們發現,每個二倍鏈的第一個數一定是奇數;如果是偶數,因為偶數一定是某個數的二倍,所以一定已經在前面的二倍鏈中出現過。另外,如果從一個二倍鏈中取某一個數,那么這個數左右兩邊的數(如果有)就不能再取了,即滿足“相鄰互斥性”。

接着,我們要計算每個二倍鏈最多能拿出多少個數構成集合S。這里先給出結論,對於長度為len的鏈,最多可以取個數構成集合S。當然這個結論需要嚴格的證明,證明過程也不難,這里做簡化說明。

當len為偶數時,只需要在二倍鏈中間隔取數即可,所以共可取len/2個數。當len為奇數時,要從第一個數開始間隔取數,這樣首尾兩個數都能取到,所以最多可以取(len + 1) / 2 個數。例如,對於二倍鏈1--2--4--8,既可以取{1, 4},也可以取{2, 8};而對於1--2--4--8--16,只能取{1, 4, 16}是最多的。所以問題轉化成求每個二倍鏈的長度。

更進一步,其實每個二倍鏈是這樣的結構(不妨設n為奇數):

PS:以上最后一個二倍鏈只有n本身。

所以每個以奇數c開始的二倍鏈的長度為,其中

故S中元素的最大個數為

同理,當n為偶數時,S中元素的最大個數為

最后再廢話一下,上面兩式可以合並為一個式子表示。假設m為小於n的最大奇數,那么

因此(1)(2)兩式可以合並寫為

 最后,當n = 50時,帶入(4)式,用matlab命令

>> sum(floor(log2(n ./ [1 : 2 : n - 1]) / 2)) + n / 2

容易求出結果為33,因此答案為D。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM