[HDOJ3709]Balanced Number(数位dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3709

题意:求区间[L,R]内每一个数中是否存在一位,使得左边的各位数*距离=右边的各位数*距离(自己和自己的距离算0)。

先枚举pivot的位置,然后做数位dp,记录当前数位、pv的位置和当前和。由于前导零的存在,最后结果要减掉诸如00,000,000...0这样的情况(个数和数位长度相同,当然单独一个0是合法的)。

最终结果ret-pos+1

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 const int maxn = 20;
 6 int digit[maxn];
 7 LL l, r;
 8 LL dp[maxn][maxn][maxn*9*20];
 9 
10 LL dfs(int l, int pv, int s, bool flag) {
11     if(l == 0) return !s;
12     if(s < 0) return 0;
13     if(~dp[l][pv][s] && !flag) return dp[l][pv][s];
14     int pos = flag ? digit[l] : 9;
15     LL ret = 0;
16     for(int i = 0; i <= pos; i++) {
17         ret += dfs(l-1, pv, s+i*(l-pv), flag&&(i==pos));
18     }
19     if(!flag) dp[l][pv][s] = ret;
20     return ret;
21 }
22 
23 LL f(LL x) {
24     int pos = 0;
25     if(x == -1) return 0;
26     while(x) {
27         digit[++pos] = x % 10;
28         x /= 10;
29     }
30     LL ret = 0;
31     for(int i = pos; i >= 1; i--) {
32         ret += dfs(pos, i, 0, true);
33     }
34     return ret - pos + 1;
35 }
36 
37 int main() {
38     // freopen("in", "r", stdin);
39     int T;
40     scanf("%d", &T);
41     memset(dp, -1, sizeof(dp));
42     while(T--) {
43         scanf("%I64d %I64d", &l, &r);
44         printf("%I64d\n", f(r)-f(l-1));
45     }
46     return 0;
47 }

 

posted @ 2016-10-13 14:49  Kirai  阅读(199)  评论(0编辑  收藏  举报