1. 程式人生 > >[HDU3709] [2010成都區域賽] Balanced Number [數位dp]

[HDU3709] [2010成都區域賽] Balanced Number [數位dp]

[ L i n k \frak{Link} ]


[a,b]中平衡數的數量。平衡數需要拆解數位判定。

看到這樣的題目很容易想到數位dp

,然而平衡數的判定不是很容易。
“一個數是平衡數,那麼在這個數裡面能找到某個平衡點,其左右數位上數的力矩和相等。”
如果數位dp的話,最大的問題就是平衡點根本不確定。
先考慮用最簡單的方法解決——直接確定平衡點,也就是列舉。

不過到了數位dp裡面,這種暴力也不是那麼暴力了。實際上這樣正好能夠通過本題。
所以把平衡點作為state就好了。
(一步討論就解決了好像有點尷尬((

不過實現的時候還是要注意的。比如不要忘記開long long


#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib> #include<cmath> #include<cctype> using namespace std; int T; long long x,y; long long F[20][20][2000]; int bit[20]; long long dfs(const int &pos, const int &state, const int &sum, const bool &lead, const bool &limit) { if(sum < 0) return 0; if(!pos)
return !sum; if(!limit && F[pos][state][sum] != -1) return F[pos][state][sum]; long long ret = 0; int up = limit ? bit[pos] : 9; for(int i = (lead && pos == state); i <= up; ++i) { ret += dfs(pos - 1, state, sum + i * (pos - state), lead && i == 0, limit && i == up); } if(!limit) F[pos][state][sum] = ret; return ret; } long long solve(long long &x) { if(x < 0) return 0; bit[0] = 0; while(x) { bit[++bit[0]] = x % 10; x /= 10; } long long ret = 0; for(int i = 1; i <= bit[0]; ++i) { ret += dfs(bit[0], i, 0, true, true); } return ret + 1; } int main() { memset(F, -1, sizeof(F)); scanf("%d", &T); for(int i = 1; i <= T; ++i) { scanf("%lld%lld", &x, &y); printf("%lld\n", solve(y) - solve(--x)); } return 0; }