题意:统计区间[L,R]中,balanced number的数字个数。balanced number即对于任意一个数字串,假设其有一个数字位,它左边的数字乘距离的和等于它右边的数字乘距离的和,
则其为balanced number.
题解:数位dp,对于这种左边和右边满足一定关系的问题,可以左右各一维,也可以左边减去右边作为一维
因为数字位不同计算的方式也是不同的,所以这里再加一维,也避免了多次初始化
设dp[pos][p][s]代表第pos位,数字位为p,左边减去右边为s,最后s == 0就是满足条件的
#include <iostream> #include <stdio.h> #include <string.h> #define maxn 1001000 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; ll dp[30][30][2000], a[35]; ll dfs(ll pos, ll p, ll s, bool limit){ if(pos == -1) return s==0;//左边-右边 if(s < 0) return 0;//从左到右,先加后减,<0说明到了右边而且还要继续减 if(!limit && dp[pos][p][s] != -1) return dp[pos][p][s]; ll t = limit?a[pos]:9; ll ans = 0; for(ll i=0;i<=t;i++){ ans += dfs(pos-1, p, s+(pos-p)*i, limit&&i == a[pos]); } if(!limit) dp[pos][p][s] = ans; return ans; } ll solve(ll x){ ll pos = 0, ans = 0; while(x){ a[pos++] = x%10; x /= 10; } for(ll i=0;i<pos;i++) ans += dfs(pos-1, i, 0, 1); ans = ans-pos+1; return ans; } int main(){ ll l, r, T; memset(dp, -1, sizeof(dp)); scanf("%lld", &T); while(T--){ scanf("%lld%lld", &l, &r); printf("%lld\n", solve(r)-solve(l-1)); } return 0; }