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 }