hdu4734 F(x) 数位dp

//对于一个十进制的数A,其每一位的权值为2^(n-1)得到的值即为
//这个数的权值,现在给出A,B
//问在区间[0,B]中的所有数权值小于等于
//A的权值的个数为多少
//dp[i][j] 表示第i位权值小于等于j的数的个数
//用记忆化搜索得到答案
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int maxn = 5e3+10 ;
int dp[12][maxn] ;
int bit[12] ;
int dfs(int pos , int sum , int lim)
{
    if(sum < 0)return 0 ;
    if(pos == 0)
    return (sum >= 0) ;
    if(!lim && dp[pos][sum] != -1)return dp[pos][sum]  ;
    int num = lim ? bit[pos] : 9 ;
    int ans = 0 ;
    for(int i = 0;i <= num;i++)
        ans += dfs(pos-1 , sum - i*(1<<(pos-1)) , lim && (i==num)) ;
    if(!lim)dp[pos][sum] = ans ;
    return ans ;
}
int main()
{
    //freopen("in.txt" , "r" , stdin) ;
    int  t ;
    int cas = 0 ;
    scanf("%d",&t) ;
    memset(dp , -1 , sizeof(dp)) ;
    while(t--)
    {
        int a , b ;
        scanf("%d%d" , &a , &b) ;
        int len = 0 ;
        while(b)
        {
            bit[++len] = b%10 ;
            b/=10 ;
        }
        int cmp = 0 ;
        int pos = 0 ;
        while(a)
        {
            cmp += (a%10)*(1<<pos) ;
            pos++ ;
            a/=10 ;
        }
        printf("Case #%d: " ,++cas) ;
        printf("%d\n" , dfs(len , cmp , 1)) ;
    }
    return 0 ;
}












































你可能感兴趣的:(hdu4734 F(x) 数位dp)