首页 > 代码库 > hdu 4734 F(x) 数位dp

hdu 4734 F(x) 数位dp

题意:定义 F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1(其中 x = AnAn-1An-2 ... A2A1),那么给定A,B,求[0,B]区间的i,满足F(i)<=F(A)

的个数。

思路:设dp[ pos ] [ k ]为当前考虑pos位,之后(pos + 1)位与之前的位数组合形成的F函数值不超过k的数的个数,详见代码:

/*********************************************************
  file name: hdu4734.cpp
  author : kereo
  create time:  2015年01月20日 星期二 11时09分03秒
*********************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cmath>
#include<string>
using namespace std;
typedef long long ll;
const int sigma_size=26;
const int N=10;
const int MAXN=6000+50;
const int inf=0x3fffffff;
const double eps=1e-8;
const int mod=100000000+7;
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define PII pair<int, int>
#define mk(x,y) make_pair((x),(y))
int res;
int bit[N],dp[N][MAXN],a[N],p[N];
int dfs(int pos,int st,int flag){
    if(pos == -1) return 1;
    if(flag && dp[pos][st]!=-1)
        return dp[pos][st];
    int ans=0;
    int x=flag ? 9 : bit[pos];
    for(int i=0;i<=x;i++){
        int k=st-(int)p[pos]*i;
        if(k<0)
            continue;
        ans+=dfs(pos-1,k,flag || i<x);
    }
    if(flag)
        dp[pos][st]=ans;
    return ans;
}
int solve(int x){
    int len=0;
    do{
        bit[len++]=x%10;
        x/=10;
    }while(x);
    return dfs(len-1,res,0);
}
int main(){
    int T,kase=0;
    scanf("%d",&T);
    p[0]=1;
    for(int i=1;i<10;i++)
        p[i]=p[i-1]*2;
    memset(dp,-1,sizeof(dp));
    while(T--){
        int A,n;
        scanf("%d%d",&A,&n);
        int cnt=0; res=0;
        do{
            a[cnt++]=A%10;
            A/=10;
            res+=p[cnt-1]*a[cnt-1];
        }while(A);
        int ans=solve(n);
        printf("Case #%d: %d\n",++kase,ans);
    }
    return 0;
}


hdu 4734 F(x) 数位dp