Problem Description
For a decimal number x with n digits (AnAn-1An-2 ... A2A1), we define its weight as F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1. Now you are given two numbers A and B, please calculate how many numbers are there between 0 and B, inclusive, whose weight is no more than F(A).
Input
The first line has a number T (T <= 10000) , indicating the number of test cases.
For each test case, there are two numbers A and B (0 <= A,B < 109)
Output
For every case,you should output "Case #t: " at first, without quotes. The t is the case number starting from 1. Then output the answer.
Sample Input
30 1001 105 100
Sample Output
Case #1: 1Case #2: 2Case #3: 13
思路:数位DP
- dp(i, j)表示枚举到第i位剩余数位权值和不超过j时的数的数量。
- 记忆化搜索即可。
Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e5 + 10; 4 long long dp[15][maxn]; 5 int a[15], temp; 6 7 int f(int x) { 8 int t = 0, ans = 0; 9 while(x) { 10 ans += x % 10 * (1 << t); 11 x /= 10; 12 ++t; 13 } 14 return ans; 15 } 16 17 long long dfs(int pos, int res, bool limit) { 18 if (res < 0) return 0; 19 if (pos == 0) return 1; 20 if (!limit && ~dp[pos][res]) return dp[pos][res]; 21 int up = limit ? a[pos] : 9; 22 long long ans = 0; 23 for (int i = 0; i <= up; ++i) 24 ans += dfs(pos-1, res-i*(1<<(pos-1)), limit && a[pos] == i); 25 if (!limit) dp[pos][res] = ans; 26 return ans; 27 } 28 29 long long cal(int x) { 30 int len = 0; 31 while(x) { 32 a[++len] = x % 10; 33 x /= 10; 34 } 35 return dfs(len, temp, 1); 36 } 37 38 int main() { 39 int T, a, b, kase = 0; 40 memset(dp, -1, sizeof(dp)); 41 cin>>T; 42 while(T--) { 43 cin>>a>>b; 44 temp = f(a); 45 cout<<"Case #"<<++kase<<": "<<cal(b)<<endl; 46 } 47 48 return 0; 49 }