查詢區間 [S, E] 中,有多少整數的二進制表示中 **0 的個數 ≥ 1 的個數**。S, E < 2³¹。多測試案例。
答案 = f(E) - f(S-1)。關鍵計算 f(x)。
int C[35][35];
void initComb() {
for (int i=0;i<=32;++i) { C[i][0]=1; for(int j=1;j<=i;++j) C[i][j]=C[i-1][j]+C[i-1][j-1]; }
}
int countValid(int x) {
if (x <= 0) return 0;
// 獲取二進制位存入 bits[], 高位在前
// 1. 統計長度 < len 的合法數
// 2. 掃描 bits,遇 1 時嘗試置 0,剩餘位組合
// 3. 最後檢查 x 自身是否合法
// 返回總數
}
狀態:`dp[pos][diff][tight]`,`diff = count0 - count1`(可為負,偏移 +16)。轉移嘗試 0/1。最後 `diff ≥ 0` 計入。狀態數 32 × 33 × 2 ≈ 2000,極簡單。
POJ 3252 既可用組合數學直接計算,也可用標準數位 DP。組合數學思路更直觀、常數更小;數位 DP 更通用、易擴展(如改條件為 0 > 1 等)。掌握兩種思維均有益。