hdu 4734 数位DP

//hdu 4734 F(x)  数位dp的题
//
//我们定义十进制数x的权值为f(x) = a(n)*2^(n-1)+a(n-1)*2^(n-2)+...a(2)*2+a(1)*1,a(i)表示十进制数x中第i位的数字。
//题目给出a,b,求出0~b有多少个不大于f(a)的数。
//
//
//dp[i][j]表示i位值<=j 的总数
//bit位由低位到高位存储
//dfs由高位到低位进行
//注意dp数组初始化那里,t了我那么多发
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<string>
using namespace std;
int len;
int cas,A,B;
int dp[20][200000];
int bit[20];

int dfs(int pos,int num,bool flag)
{
    if(pos==-1)  return num>=0;///关于0的处理在这里
    if(num<0)   return 0;
    if(!flag&&dp[pos][num]!=-1)  return dp[pos][num];///记忆化搜索。。减少时间什么的
    int endd=flag?bit[pos]:9;
    int ans=0;
    for(int i=0;i<=endd;i++)
    {
        ans+=dfs(pos-1,num-i*(1<<pos),flag&&(i==endd));//如果到了结尾就要用bit[pos]不能用9
        ///一开始卡在这里,<<是左移运算符,不是乘二运算符,要加1<<pos!!!
    }
    if(!flag)
        dp[pos][num]=ans;//不到最后一位,不能统计这一位的dp值
    return ans;
}

int f(int x)
{
    int ret=0,num=0;
    while(x)
    {
        ret+=(x%10)*(1<<num);
        x/=10;
        num++;
    }
    return ret;
}



int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d",&cas);
    memset(dp,-1,sizeof(dp));///最大的优化在于dp数组初始化在外面,因为跑的是一样的。下面的可以接着用
    for(int ca=1;ca<=cas;ca++)
    {

        scanf("%d%d",&A,&B);
        int len=0;
        while(B)
        {
        bit[len++]=B%10;
        B/=10;
        }
        printf("Case #%d: %d\n",ca,dfs(len-1,f(A),true));
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值