hdu 4734 F(x)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4734
题意:给出一个数x包含n位(AnAn-1An-2 ... A2A1),定义F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1。
给出两个数字A, B,求0-B的数字中,满足F(X) <= F(A)的数有多少个。
思路:先求出F(A),定义dp[cur][rest],表示当前搜索到第cur位,剩余可以使用的大小还有rest,初始剩余大小就是F(A)。
然后用记忆化搜索。
1 #include <bits/stdc++.h> 2 using namespace std; 3 int numa[12], numb[12]; 4 int p[12]; 5 int dp[12][5000]; 6 void init() 7 { 8 memset(dp, -1, sizeof(dp)); 9 p[0] = 1; 10 for(int i = 1; i <= 10; i++) p[i] = p[i-1]*2; 11 } 12 int F(int x) 13 { 14 int cnt = 0; 15 while(x) 16 { 17 numa[cnt++] = x%10; 18 x /= 10; 19 } 20 int sum = 0; 21 for(int i = cnt-1; i >= 0; i--) sum += p[i]*numa[i]; 22 return sum; 23 } 24 25 int A, B; 26 int dfs(int cur, int rest, int limit) 27 { 28 if(cur < 0) 29 { 30 if(rest >= 0) return 1; 31 else return 0; 32 } 33 if(!limit && dp[cur][rest] != -1) return dp[cur][rest]; 34 35 int ret = 0; 36 int up = limit?numb[cur]:9; 37 for(int i = 0; i <= up; i++) 38 { 39 int nowrest = rest- i*p[cur]; 40 if(nowrest < 0) continue; 41 ret += dfs(cur-1, nowrest, limit && i == up); 42 } 43 if(!limit) dp[cur][rest] = ret; 44 return ret; 45 } 46 int slove(int x) 47 { 48 int cnt = 0; 49 while(x) 50 { 51 numb[cnt++] = x%10; 52 x /= 10; 53 } 54 return dfs(cnt-1, F(A), 1); 55 } 56 int main() 57 { 58 init(); 59 // freopen("in.txt", "r", stdin); 60 int T; 61 scanf("%d", &T); 62 int cast = 0; 63 while(T--) 64 { 65 cast++; 66 scanf("%d%d", &A, &B); 67 printf("Case #%d: %d\n", cast, slove(B)); 68 69 } 70 return 0; 71 }