HDU 4734

题意:给出a, b两个数, 求0到b不大于f(a)的数的个数, F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A 1 * 1. An表示a对于位上的值
用数位DP,这里讲的比较详细http://www.cnblogs.com/Griselda/archive/2013/11/20/3433295.html


#include <stdio.h>
#include <string.h>
int w[12], dp[10][200000];
int dfs(int len, int pre, bool flag)
{
    if(len < 0) return pre >= 0;
    if(pre < 0) return 0;
    if(!flag && dp[len][pre] != -1) return dp[len][pre];//已经求得
    int End = flag?w[len]:9, ans = 0;
    for(int i = 0;i <= End;i++)
        ans += dfs(len - 1, pre - i*(1 << len), flag&&i == End);
    if(!flag) dp[len][pre] = ans;
    return ans;
}
int f(int a)
{
    int p = 1, sum = 0;
    while(a > 0)
    {
        sum += (a % 10) * p;
        p *= 2;
        a /= 10;
    }
    return sum;
}
int slove(int a, int b)
{
    int top = 0;
    while(b > 0)
    {
        w[top++] = b % 10;
        b /= 10;
    }
    return dfs(top - 1, f(a), true);
}
int main()
{
    int t, i, a, b;
    scanf("%d", &t);
    memset(dp, -1, sizeof(dp));
    for(i = 1;i <= t;i++)
    {
        scanf("%d %d", &a, &b);
        printf("Case #%d: %d\n", i, slove(a, b));
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值