HDU4734 F(x) 数位dp

来源:互联网 发布:mac怎么给iphone换铃声 编辑:程序博客网 时间:2024/06/10 07:47
For a decimal number x with n digits (A nn-1n-2 ... A 21), we define its weight as F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A 1 * 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 < 10 9)
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
题意:输入N,然后分别有N组数据,每次输入两个数a,b;a表示F[a],题意让求x在[0,b]区间内有多少满足F[x]<=F[a];F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A 1 * 1;
的意思是x的第n位的数字乘以2的(n-1)次方的和,如x=5,则F[x]=5*2^0=5;   再如:x=15,则F[x]=1*2^1+5*2^0=7;对于第三组样例:满足F[a]>=F[x]的条件的x有:0,1,2,3,4,5,10,11,12,13,20,21,100,共13个;
思路就是数位dp的思想,暴力枚举,求得满足的数,dp[i][j],i代表位,j代表F[x];
思路与前两个题一样  很清晰,直接套模板也行:
代码如下:
#include<cstdio>#include<cstring>int dp[10][10005];//F[x]最大不会超过一万 int a[10];int A,b;int sum;int dfs(int pos,int s,bool limit){if(pos == -1) return s <= sum;if(s > sum) return 0;if(!limit && dp[pos][sum-s] != -1) return dp[pos][sum-s];int up = limit ? a[pos] : 9;int tmp = 0;for(int i = 0; i <= up; i++){tmp += dfs(pos - 1 , s + i * (1 << pos),limit && i == a[pos]);}if(!limit) dp[pos][sum-s] = tmp;return tmp;}int F(int x){int p = 1,s = 0;while(x){s += p * (x % 10);x /= 10;p *= 2;}return s;}int solve(int x){int t = 0;while(x){a[t++] = x%10;x /= 10;}return dfs(t-1,0,true);}int main(){int N,M = 1;scanf("%d",&N);memset(dp,-1,sizeof(dp));while(N--){scanf("%d %d",&A,&b);sum = F(A);printf("Case #%d: %d\n",M++,solve(b));}return 0;}

原创粉丝点击