hdu 4734 F(x) 数位DP

一,题意:

该题定义了一个函数 : F(x)=An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1。

 现在他给定两个数,A,B,要求你求出在区间[0,B] 有多少个x ,使得F(x)<=F(A)。

二,解析:

该题主要应用了,数位dp的思想+记录状态dp的思想。

1,数位dp思想主要数是用数组来存储数,通过对数组每一位进行枚举(0,1,2,,,9),

到达便利区间[0,N]内所有数的目的

例如: 比456小的数,可以这么考虑:

这样就可以遍历[0,456]区间所有的数。

2,记录状态思想,记录下程序已走过的路,当在次走相同的路时直接返回。

至于这么判断是否走同一条路是一般是通过函数参数值,如果用同样的参数去调用同一个函数则所走的路必然是相同的。

所以dp[i][j],数组下标i,j一般表示的就是调用函数的参数。

三:代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
int T,N,M;
int bit[15];
int Max[15];
int dp[15][200000];
//dp[len][sum]表示长度为len且权值不大于sum的数的个数。
int DFS(int len,int sum,bool Big)
{//len所搜索到的长度,sum是F[N]剩余的部分,big标记前驱是不是最大数
    if(sum<0)
        return 0;
    if(len<=0)
        return 1;//两个边界
    if(!Big&&dp[len][sum]!=-1)
        return dp[len][sum];//记录状态
    int bian=9;
    if(Big)//第len位的边界
        bian=Max[len];
    int key=0;
    for(int i=0;i<=bian;i++)
        key+=DFS(len-1,sum-(i*bit[len]),Big&&(i==bian));
    if(!Big)
        dp[len][sum]=key;
    return key;
}
int solve(int n,int m)
{
    int key=0;
    int len=1;
    while(n)
    {//计算F[N]
       key=key+(n%10)*bit[len];
       len++;
       n=n/10;
    }
    len=0;
    while(m)
    {//分解M
        Max[++len]=m%10;
        m=m/10;
    }
    return DFS(len,key,true);
}

int main()
{
    bit[1]=1;
    for(int i=2;i<=11;i++)
        bit[i]=bit[i-1]*2;
    memset(dp,-1,sizeof(dp));
    scanf("%d",&T);
    for(int k=1;k<=T;k++)
    {
        scanf("%d%d",&N,&M);
        printf("Case #%d: %d\n",k,solve(N,M));
    }
    return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值