在資訊學競賽中,有這樣一類問題:求給定區間中,滿足給定條件的某個d 進製數或 此類數的數量。所求的限定條件往往與數字有關,例如數字之和、指定數碼個數、數的大小 順序分組等等。題目給定的區間往往很大,無法採用樸素的方法求解。此時,我們就需要利用數字的性質,設計 log(n)級別複雜度的演算法。解決這類問題最基本的思想就是「逐位確定」 的方法。下面就讓我們通過幾道例題來具體了解一下這類問題及其思考方法。
【例題 1】amount of degrees (ural 1057)
題目大意:
求給定區間[x,y]中滿足下列條件的整數個數:這個數恰好等於k 個互不相等的 b 的整 數次冪之和。
分析: 所求的數為互不相等的冪之和,亦即其b 進製表示的各位數字都只能是 0和 1。因此, 我們只需討論二進位制的情況,
其他進製都可以轉化為二進位制求解。 很顯然,資料範圍較大,不可能採用列舉法,演算法複雜度必須是 log(n)級別,
因此我們 要從數字上下手。
本題區間滿足區間減法,因此可以進一步簡化問題:令 count[i..j]表示[i..j]區間內合法數 的個數,
則count[i..j]=count[0..j]-count[0..i-1]。換句話說,給定 n,我們只需求出從0 到 n 有多少個符合條件的數。
假設 n=13,其二進位制表示為 1101,k=3。我們的目標是求出 0 到 13 中二進位制表示含 3 個 1 的數的個數。為了方便思考,讓我們畫出一棵高度為 4 的完全二叉樹:
為了方便起見,樹的根用 0 表示。這樣,這棵高度為4 的完全二叉樹就可以表示所有 4 位二進位制數(0..2^4-1) ,每乙個葉子節點代表乙個數。其中,紅色路徑表示 n。所有小於 n的 數組成了三棵子樹,分別用藍色、綠色、紫色表示。因此,統計小於 13 的數,就只需統計 這三棵完整的完全二叉樹:統計藍子樹內含 3 個 1 的數的個數、統計綠子樹內含 2 個1 的數 的個數(因為從根到此處的路徑上已經有 1 個 1),以及統計紫子樹內含 1個 1 的數的個數。
注意到,只要是高度相同的子樹統計結果一定相同。而需要統計的子樹都是「右轉」時遇到 的。當然,我們不能忘記統計n 本身。
實際上,在演算法最初時將 n 自加 1,可以避免討論 n 本身,但是需要注意防止上溢。 剩下的問題就是,如何統計一棵高度為 i的完全二叉樹內二進位制表示中恰好含有 j 個1 的數的個數。這很容易用遞推求出:
設 f[i,j]表示所求,則分別統計左右子樹內符合條件數的 個數,有f[i,j]=f[i-1,j]+f[i-1,j-1]。 這樣,我們就得出了詢問的演算法:首先預處理 f,然後對於輸入 n,我們在假想的完全 二叉樹中,從根走到 n所在的葉子,每次向右轉時統計左子樹內數的個數。
下面是 c++**:
void init()
}int calc(int x,int k) //統計[0...x]內二進位制表示含有k個1的數的個數
while (x>0);
for(int i=0;i'1')
。 分析: 我們首先考慮 m、n同正的情況。 由於排序的第一關鍵字是 1 的數量,第二關鍵字是數的大小,
因此我們很容易確定答案 中 1 的個數:依次統計區間[m,n]內二進位制表示中含 1的數量為 0,1,2,…的數,直到累加的答 案超過 k,
則當前值就是答案含 1 的個數,假設是 s。利用例一的演算法可以解決這個問題。 同時,我們也求出了答案是第幾個[m,n]中含 s個 1 的數。因此,只需二分答案,求出[m,ans] 中含 s 個 1 的數的個數進行判斷即可。
由於每次詢問的複雜度為 o(log(n)),故二分的複雜度為 o(log2(n)),這同時也是預處理 的複雜度,因此此演算法較為理想。
m<0 的情況,也不難處理,我們只要忽略所有數的最高位,求出答案後再將最高位賦回 1 即可。或者也可以直接將負數視為 32位無符號數,採用同正數一樣的處理方法。兩種方 法都需要特別處理 n=0 的情況.
最終**:
//題目:spoj 1182
#include#includeusing namespace std;
int f[32][32];
void init()
}int calc(int x,int k)
{ if (x<0) return 0;
int tot=0,ans=0;
for (int i=31;i>0;--i)
{ if (x&(1u
x=x^(1u動態規劃10_數字dp2會繼續講解例題。。。
DP1 動態規劃概述
計數求最大值最小值 求存在性 確定狀態 簡單的說,就是解動態規劃時需要開乙個陣列,陣列的每個元素f i 或者f i j 代表什麼,類似解數學題中,xyz代表什麼一樣,具體分為下面兩個步驟 轉移方程 根據子問題定義直接得到 初始條件和邊界情況 初始條件一般都是a 0 a 1 這種,多看看邊界條件主要是...
DP1線性動態規劃 題
例4 lcs 最長公共子串行 乙個給定序列的子串行是在該序列中刪去若干元素後得到的序列。確切地說,若給定序列x 若另一串行z 是x的子串行,是指存在乙個嚴格遞增的下標序列 使得對於所有j 1,2,k有 例如,序列z 是序列x 的子串行,相應的遞增下標序列為 2,3,5,7 給定兩個序列x和y 當另一...
動態規劃 線性DP 1
動態規劃演算法通常用於求解具有某種最優性質的問題。那它和貪心有區別嗎?當然有。不然叫動態規劃幹啥?幼兒園英語老師 dp是啥?小盆友 dog peppa pig 英語老斯 恩恩!真聰明!然而,你是小盆友嗎?如果是 如果不是,dp是d p 的縮寫。意思是動態規劃。聰明的bolt告訴你 是dynamic ...