[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 }