题目链接:[kuangbin带你飞]专题十五 数位DP F - Balanced Number
题意
给定区间[a,b],求区间内平衡数的个数。所谓平衡数即有一位做平衡点,左右两边数字的力矩想等。
思路
遍历每一位做为平衡点,进行搜索,sum保存数字乘以距离的和,若sum为0,则说明平衡。
要注意因为遍历了len次,所以0多加了len-1次。
还有个小技巧是当sum<0时就可以直接return了,可以加速。因为,len由大到小的过程中,sum是由大到小的变化,但绝不会小于0,否则就是不能平衡。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
#define LL long long
LL dp[20][20][2000];
int dis[20];
LL dfs(int len, int pos, int sum, bool flag)
{
if(len < 0)
return sum?0:1;
if(sum < 0)
return 0;
if(!flag && dp[len][pos][sum] != -1)
return dp[len][pos][sum];
LL ans = 0;
int end = flag?dis[len]:9;
for(int i=0; i<=end; i++)
{
ans += dfs(len-1, pos, sum+(len-pos)*i, flag&&i==end);
}
if(!flag)
dp[len][pos][sum] = ans;
return ans;
}
LL solve(LL n)
{
int len = 0;
while(n)
{
dis[len++] = n%10;
n /= 10;
}
LL ans = 0;
for(int i=0; i<len; i++)
ans += dfs(len-1, i, 0, 1);
return ans - (len-1);
}
int main()
{
int T;
scanf("%d", &T);
memset(dp, -1, sizeof(dp));
while(T--)
{
LL l, r;
scanf("%lld%lld", &l, &r);
printf("%lld\n", solve(r) - solve(l-1));
}
return 0;
}