题目链接: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;
}

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

被折叠的 条评论
为什么被折叠?



