【数位dp入门】【HDU4734】F(x)

记录减的状态,表示还要凑多少才能达到当前值。

然后进行枚举即可。注意状态数不能重复。

#include<bits/stdc++.h>
#define N 10010
using namespace std;
int dp[12][N],a[N],val;
int f(int x){
    if(!x)return 0;
    return f(x/10)*2+(x%10);
}
int dfs(int x,int sum,int lim){
    if(x==-1)return sum<=val;if(sum>val)return 0;
    if(!lim&&dp[x][val-sum]!=-1)return dp[x][val-sum];
    int maxv=lim?a[x]:9;int ret=0;
    for(int i=0;i<=maxv;i++)
        ret+=dfs(x-1,sum+i*(1<<x),lim&&i==a[x]);
    if(!lim)dp[x][val-sum]=ret;
    return ret;
}
inline int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
inline int work(int x){
    int len=0;
    while(x){a[len++]=x%10;x/=10;}
    return dfs(len-1,0,1);
}
int main(){
    int T=read(),cnt=0;
    memset(dp,-1,sizeof(dp));
    while(T--){
        int x=read(),r=read();
        val=f(x);
        printf("Case #%d: %d\n",++cnt,work(r));
    }
}

 

posted @ 2017-06-12 09:14  zcysky  阅读(235)  评论(0编辑  收藏  举报