hdu 3709 Balanced Number 数位dp

题目链接

一个数称为平衡数, 只要他的某一位满足, 这一位左边的所有数sigma x*(x距离这一位的距离)等于右边的sigma x*(x距离这一位的距离), 例如4139, 3就满足这个性质, 因为4*2+1*1 == 9*1。

求出一个范围内的平衡数的数量。

看起来好麻烦, 不好想状态, 但是我们可以枚举每一位作为支点, 这样问题就简化了许多。具体看代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define mem1(a) memset(a, -1, sizeof(a))
 5 ll dp[20][20][4000], digit[20];
 6 ll dfs(int len, int center, int sum, bool fp) {
 7     if(!len) {
 8         return sum==0;
 9     }
10     if(!fp&&dp[len][center][sum]!=-1)           //center是支点, sum是和
11         return dp[len][center][sum];
12     ll maxx = fp?digit[len]:9, ret = 0;
13     for(int i = 0; i<=maxx; i++) {
14         ret += dfs(len-1, center, sum+i*(center-len), fp&&i==maxx);
15     }
16     if(!fp)
17         return dp[len][center][sum] = ret;
18     return ret;
19 }
20 ll cal(ll n) {
21     int len = 0;
22     while(n) {
23         digit[++len] = n%10;
24         n/=10;
25     }
26     ll ret = 0;
27     for(int i = 1; i<=len; i++) {
28         ret += dfs(len, i, 0, 1);           //枚举每一位
29     }
30     return ret-(len-1);         //因为每次计算了len个0, 而我们只需要一个0
31 }
32 int main()
33 {
34     ll a, b, t;
35     mem1(dp);
36     cin>>t;
37     while(t--) {
38         scanf("%I64d%I64d", &a, &b);
39         printf("%I64d\n", cal(b)-cal(a-1));
40     }
41 }

 

posted on 2015-12-10 17:50  yohaha  阅读(136)  评论(0编辑  收藏  举报

导航