HDU - 3709 Balanced Number 数位dp

本文介绍了一种通过动态规划和深度优先搜索解决平衡数问题的方法。利用递归函数dfs进行遍历,通过调整中心轴来确保数值平衡。该算法考虑了状态压缩技巧,有效地减少了空间复杂度。

题目链接:Balanced Number

枚举中心轴,然后dfs即可。

很容易就想到定义状态为dp[pos][pivot][left][right],pos为当前数位,pivot为中心轴,left为中心轴左边的权值和,right为中心轴右边的权值和。临界条件判断left是否等于right。

我们知道左右两边的权值和最大值大约是1500,这样一来空间复杂度就变成了18 * 18 * 1500 * 1500,会MLE。

其实第四维可以省掉,在中轴之前权值不断增加,在中轴之后让权值不断减小就行了,临界条件判断权值是不是等于0即可。

代码如下:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>

using namespace std;

typedef long long int LL;
LL dp[20][20][2000];
int digit[20];

LL dfs(int pos, int pivot, int pre, int limit)
{
    if (!pos)
        return pre == 0;
    if (!limit && dp[pos][pivot][pre] != -1)
        return dp[pos][pivot][pre];
    if (pre < 0)
        return 0;
    int up = limit ? digit[pos] : 9;
    LL ans = 0;
    for (int i = 0; i <= up; i++)
        ans += dfs(pos - 1, pivot, pre + i * (pos - pivot), limit && i == up);
    return limit ? ans : dp[pos][pivot][pre] = ans;
}

LL cal(LL n)
{
    if (n < 0)
        return 0;
    int len = 0;
    while (n)
    {
        digit[++len] = n % 10;
        n /= 10;
    }
    LL ans = 0;
    for (int i = len; i >= 1; i--)
        ans += dfs(len, i, 0, 1);
    return ans - len + 1;  // 0会重复计算
}

int main()
{
	//freopen("test.txt", "r", stdin);

    int T;
    scanf("%d", &T);
    memset(dp, -1, sizeof(dp));
    while (T--)
    {
        LL x, y;
        scanf("%I64d%I64d", &x, &y);
        printf("%I64d\n", cal(y) - cal(x - 1));
    }
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值