HDU 4734 数位DP

来源:互联网 发布:程序员客栈 编辑:程序博客网 时间:2024/06/05 06:10

数位DP

题意:

​ 定义:F(x)=An2n1+An12n2+...+A22+A11 为一个数子x的权重,现在给出一个数字A,可以求出它的权重,问0~B之间有多少权重小于等于A的权重的数字。

思路:

​ 考虑到A的范围,它的权重最大也不超过10000,所以可以定义:

dp[i][sum] 第i位数字里面所有满足权重小于等于sum 的个数。

​ 那么按照简单数位DP就可以很容易写出来。

  • 注意边界条件
#include <iostream>#include <cstdio>#include <cstring>using namespace std;int A,B,bit[10];int dp[10][10005];int F(int x){    int ans = 0;    int len = 0;    while(x) {        ans += (x%10)*(1<<len);        len++;        x /= 10;    }    return ans;}int dfs(int pos,int sum,int e){    if(pos == -1) return sum >= 0;    if(sum < 0) return 0;    if(!e && dp[pos][sum] != -1) return dp[pos][sum];    int End = e ? bit[pos] : 9;    int ans = 0;    for(int i = 0;i <= End; i++) {        ans += dfs(pos-1,sum - i*(1<<pos),e && i == End);    }    if(!e) dp[pos][sum] = ans;    return ans;}int solve(){    int pos = 0;    while(B) {        bit[pos++] = B%10;        B /= 10;    }    return dfs(pos-1,F(A),1);}int main(){    //freopen("in.txt","r",stdin);    int tt,ncase = 1;    scanf("%d",&tt);    memset(dp,-1,sizeof(dp));    while(tt--) {        scanf("%d%d",&A,&B);        printf("Case #%d: %d\n",ncase++,solve());    }    return 0;}