hdu 4734 F(x) (数位DP)

题目链接
题意:给定F(x)的公式,同时给定a和b,问你【0,b】区间内有多少数i满足F(i)<=F(a)
思路:标准的数位DP模板题,可以把F(a)先求出来,记忆化搜索的时候记录可行的状态(即pre),也就是pre-i*(1<<pos)大于0的时候pre状态时合法的,因为此时才说明F(a)比较大。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+1;
int dp[20][maxn],mx[20];
int f(int a)
{
    int temp=1,ans=0;
    while(a)
    {
        ans+=a%10*temp;
        a/=10;
        temp<<=1;
    }
    return ans;
}
int dfs(int pos,int pre,bool limit)
{
    if(pos<0) return pre>=0;
    if(pre<0) return 0;//不是可行状态
    int up=limit?mx[pos]:9,ans=0;
    if(!limit&&dp[pos][pre]!=-1) return dp[pos][pre];
    for(int i=0;i<=up;++i)
    {
        ans+=dfs(pos-1,pre-i*(1<<pos),limit&&i==up);
    }
    if(!limit) dp[pos][pre]=ans;
    return ans;
}
int solve(int a,int b)
{
    int len=0;
    while(b)
    {
        mx[len++]=b%10;
        b/=10;
    }
    return dfs(len-1,f(a),true);
}
int main()
{
    int T,a,b,j=0;
    memset(dp,-1,sizeof(dp));
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d",&a,&b);
        printf("Case #%d: %lld\n",++j,solve(a,b));
    }
 } 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值