HDU 3709 Balanced Number(数位DP)
题目链接:https://cn.vjudge.net/contest/163023#problem/F
题目大意:对于某个数字,以其中一位为支点,分成左右两边。如果左右两部分的 sigma(d[i] * | i - fixloc |)相等,那它就是Balaced Number。比如:4139以3为分界点4*2+1*1=9 and 9*1=9。所以它是。
题目分析:
首先要分析出,对于某个非 0 的 number,最多可能有一个 pivot 的位置。
证明:如果有两个这样的位置,将左边位置移动到右边时,左边的 sigma 一定增大,右边的 sigma 最多保证不减,不可能增大,故不可能再次相等。
于是可以枚举这样的位置,然后分类统计求和。
由于 0 对于每个位置都会被统计到,最后要再减去重复的。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int data[20];
ll dp[20][20][2000];
ll dfs(int pos, int o, int sum, bool limit)
{
if(pos == -1) return sum == 0;
if(!limit && dp[pos][o][sum] != -1) return dp[pos][o][sum];
int up = limit ? data[pos] : 9;
ll ans = 0;
for(int i = 0; i <= up; i++)
{
int v = sum + i * (pos - o);
ans += dfs(pos - 1, o, v, i == data[pos] && limit);
}
if(!limit) dp[pos][o][sum] = ans;
return ans;
}
ll solve(ll n)
{
int pos = 0;
while(n)
{
data[pos++] = n % 10;
n /= 10;
}
ll ans = 0;
for(int i = 0; i < pos; i++)
ans += dfs(pos - 1, i, 0, true);
//减去00, 000. 0000
return ans - pos + 1;
}
int main()
{
int t;
ll a, b;
scanf("%d", &t);
memset(dp, -1, sizeof(dp));
while(t--)
{
scanf("%lld %lld", &a, &b);
printf("%lld\n", solve(b) - solve(a - 1));
}
}