loj 1032 数位dp
题目链接:http://lightoj.com/volume_showproblem.php?problem=1032
思路:数位dp, 采用记忆化搜索, dp[pos][pre][have] 表示 pos处,前一位为pre, 当前有have个满足条件的状态。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 long long dp[34][2][34]; 8 int n, digit[34]; 9 10 long long dfs(int pos, int pre, int have, int doing) 11 { 12 if (pos == -1) { 13 return have; 14 } 15 if (!doing && dp[pos][pre][have] != -1) { 16 return dp[pos][pre][have]; 17 } 18 int end = doing ? digit[pos] : 1; 19 long long ans = 0; 20 for (int i = 0; i <= end; i++) { 21 int nhave = have; 22 if (pre == 1 && i == 1) { 23 nhave++; 24 } 25 ans += dfs(pos - 1, i, nhave, i == end && doing); 26 } 27 if (!doing) { 28 dp[pos][pre][have] = ans; 29 } 30 return ans; 31 } 32 33 long long Solve(int n) 34 { 35 int pos = 0; 36 while (n) { 37 digit[pos] = n % 2; 38 n /= 2; 39 pos++; 40 } 41 return dfs(pos - 1, 0, 0, 1); 42 } 43 44 int main() 45 { 46 memset(dp, -1, sizeof(dp)); 47 int _case, t = 1; 48 scanf("%d", &_case); 49 while (_case--) { 50 scanf("%d", &n); 51 printf("Case %d: %lld\n", t++, Solve(n)); 52 } 53 return 0; 54 } 55 56 57