[HDU3709] [2010成都區域賽] Balanced Number [數位dp]
阿新 • • 發佈:2018-10-31
求[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;
}