MYF

HDU 3709 Balanced Number

题目链接

HDU 3709

题目类型:数位DP

题目分析

题目大意

平衡数的定义:该数字中选定一个中心点,中心点左边的值乘以到中心点的距离之和等于右边的值乘以到中心点的距离之和

解析

这道数位DP和前几题不太一样,前面的是要求和上一位有关,而这道题是要求和中心点有关,所以我们要枚举所有中心点的情况,此外,还要枚举左右两边的和,我们可以用两个变量分别表示左边的和以及右边的和,同样也可以用一个变量看左边的和减去右边的和是否等于零。求和的话我们可能连着左边18位都是9的情况,这种情况下我们求和的最大值可能就为9*17 + 9*16 + 9*15 +...+ 9*1总之,我们开2000的话肯定是够了。想清楚了状态表示什么就不难想转移方程了,和普通的数位DP一样找即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <bitset>
#include <cstring>
#include <iostream>
#include <iosfwd>
#include <deque>
#include <algorithm>
#define Memset(a,val) memset(a,val,sizeof(a))
#define PI acos(-1.0)
#define PB push_back
#define MP make_pair
#define rt(n) (i == n ? '\n' : ' ')
#define hi printf("Hi----------\n")
#define debug(x) cout<<"Debug : ---"<<x<<"---"<<endl;
#define debug2(x,y) cout<<"Debug : ---"<<x<<" , "<<y<<"---"<<endl;
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int maxn=30+5;
const int mod=1000000007;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
ll dp[20][20][2000]; //pos pivot sum
int num[20];
ll dfs(int pos, int pivot,int sum, bool limit){
if (pos == 0)
return sum == 0;

if (!limit && dp[pos][pivot][sum]!=-1)
return dp[pos][pivot][sum];

int mx = limit ? num[pos] : 9;
ll ret = 0;
for (int i=0; i<=mx; i++) {
int newSum = sum + (pos - pivot) * i;
if (newSum >= 0) {
ret += dfs(pos-1, pivot, newSum , limit && i==mx);
}
}
if (!limit) {
dp[pos][pivot][sum] = ret;
}
return ret;
}
ll solve(ll x){
Memset(dp, -1);
int pos = 0;
while (x!=0) {
num[++pos] = x % 10;
x/=10;
}
ll ans = 0;
for (int i=1; i<=pos; i++) {
ans += dfs(pos, i, 0, 1);
}
return ans - (pos - 2); //remove the count of '0000', '000', '00' when pos==5
}
int main(){
ll l,r;
int T;
scanf("%d",&T);
while (T--) {
scanf("%lld%lld",&l,&r);
cout<<solve(r) - solve(l-1)<<endl;
}
return 0;
}