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 }