hdu 4734 F(x) 数位DP

来源:互联网 发布:微信小说网站源码 编辑:程序博客网 时间:2024/03/29 14:59

一,题意:

该题定义了一个函数 : 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 0
原创粉丝点击