hdu 4734 F(x) 数位DP

来源:互联网 发布:动画演示软件 编辑:程序博客网 时间:2024/05/21 11:29
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. Thet 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
 题意:给定A和B,求给定区间1~B中的x对应的f(x)小于f(A)的数。
F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1;
思路:简单的数位DP+记忆化搜索,唯一注意的一点是初始化DP的时候要放在外面防止超时;
代码:
#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;int dp[15][50000],b[15];int f(int n){    int ans=0,t=1;    while(n)    {        ans+=(n%10)*t;        t=t*2;        n=n/10;    }    return ans;}int dfs(int len,int ans,int flag){    if(len<=0&&ans>=0)        return 1;    if(ans<0)        return 0;    if(!flag&&dp[len][ans]!=-1)        return dp[len][ans];    int end=flag?b[len]:9;    int s=0;    for(int i=0;i<=end;i++)    {        s=s+dfs(len-1,ans-i*(1<<(len-1)),flag&&i==end);    }    if(!flag)        dp[len][ans]=s;    return s;}int find(int n,int m){    int len=0;    while(m)    {        b[++len]=m%10;        m=m/10;    }    return dfs(len,f(n),1);}int main(){    int t;    scanf("%d",&t);    memset(dp,-1,sizeof(dp));  //注意放在外面    for(int T=1;T<=t;T++)    {        int n,m;        scanf("%d%d",&n,&m);        printf("Case #%d: ",T);        printf("%d\n",find(n,m));    }}


0 0