二進制拆分


在網絡上找的我好辛苦啊!!!因為本人太蒟了,看了好多博客都沒看懂,然后莫名秒懂。

 

原理:一個數能夠被拆分為任意二進制的和。 (這個原理造出來好多算法啊QAQ)

T=2p1+2p2+2p3+...+2pn

而且       小於等於       T的所有整數都能被2p1       2p2      2p3      ....     2pn的和表示出來

 

證明我不會,但是我知道任意一個數都有自己的二進制形式,比如     13=1101

小於等於13的二進制數肯定不會超過4位,對於T如果有K位,那么小於等於T的數都不可能大於K位

(因為21 + 22 + 23 ...  + 2p-1   = 2p  - 1)

網絡上有個例子就是什么:

20+21+22能表示出1到7的任意整數,那么20+21+22+ 6就能表示出1~13的整數

這個例子的剖析就是說:

一個數表示拆成小於它的所有二的次方的和(這個二次方的指數要是遞增的)后會剩下一個數。

 

然后我們這樣拆分之后就能用log(n)個數表示出 你想表示出來的1~n中的任意數了

放個二進制拆分的例子直觀的感受一下它的用途:

多重背包;

眾所周知多重背包的朴素算法就是如果第i件物品有 ki 個,那么我們不妨將i物品直接復制為ki個然后做01背包

這樣的時間復雜度是O(nmΣki)的;

這玩意很容易超時啊!!!

算法的復雜度瓶頸就在與我們把物品分成ki個做01背包了,

但是你可以把ki進行二進制拆分,把物品欄中加入重量為wi * (2p),體積為vi *(2p)的物品了

這樣拆分后與拆成ki個物品做零一背包是等效的,因為同樣都可以表示出加入當前i物品1~ki個的價值以及重量

然后時間復雜度就優化到了O(nmlog(Σki))

核心代碼為:

  for(int i = 1 ; i <= n ; i ++)  
   for (int j = 1 ; j <= k[i] ; j <<=1)
   t++,val[t]=j*v[i],waste[t]=j*w[i];           

 


免責聲明!

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



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