HDU-3709 Balanced Number 数位dp+枚举

一个数字是平衡数字,当且仅当存在它的一个数位作为平衡点,这个点左边和右边【数字*到这个点的距离】之和相等

容易知道一个平衡数字只有一个平衡位置

设状态为dp[pos][n][sum]表示当前第pos位,平衡点在n,当前的距离为sum,枚举平衡位置

距离不取绝对值,这样sum最终为0就是可行解,而且sum小于0就可以剪枝加快速度

那么枚举时计算sum就是先正后负也就是pos-n而非n-pos,从高位往低位枚举每次sum+(pos-n)*i在n点前一定是正数

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define LL long long
 5 using namespace std;
 6 
 7 int a[20];
 8 LL dp[20][20][3000];
 9 
10 LL dfs(int pos, int sum, int len, bool lim){
11     if (pos == -1) return sum == 0;
12     if (sum < 0) return 0;
13     if (!lim && dp[pos][len][sum] != -1) return dp[pos][len][sum];
14     LL ans = 0;
15     int r = lim ? a[pos] : 9;
16     for (int i = 0; i <= r; i++)
17         ans += dfs(pos-1, sum+(pos-len)*i, len, lim && i == a[pos]);
18     if (!lim) dp[pos][len][sum] = ans;
19     return ans;
20 }
21 
22 LL solve(LL x){
23     int pos = 0;
24     while (x){
25         a[pos++] = x%10;
26         x /= 10;
27     }
28     LL ans = 0;
29     for (int i = 0; i < pos; i++)
30         ans += dfs(pos-1, 0, i, 1);
31     return ans - pos + 1;
32 }
33 
34 int main(){
35     int t;
36     LL l, r;
37     scanf("%d", &t);
38     memset(dp, -1, sizeof dp);
39     while (t--){
40         scanf("%lld%lld", &l, &r);
41         printf("%lld\n", solve(r)-solve(l-1));
42     }
43     return 0;
44 }

猜你喜欢

转载自www.cnblogs.com/QAQorz/p/9359558.html