题目链接:Click here~~
题意:
对于某个 number,你可以 fix a pivot 在某位,然后如果分成的左右两部分的 sigma(d[i] * | i - fixloc |)相等,则它是 Balanced Number。
统计区间 [a,b] 中Balance Number 的个数。
解题思路:
首先要分析出,对于某个非 0 的 number,最多可能有一个 pivot 的位置。
证明:如果有两个这样的位置,将左边位置移动到右边时,左边的 sigma 一定增大,右边的 sigma 最多保证不减,不可能增大,故不可能再次相等。
于是可以枚举这样的位置,然后分类统计求和。
由于 0 对于每个位置都会被统计到,最后要再减去重复的。
Ps:在 数位dp 的 dfs 中,对于 0 的看待,是 len 个0 放一起,以后这个细节要注意。
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long LL;
LL dp[20][20][1800];
int digit[20];
LL dfs(int len,int fixloc,int sum,bool fp)
{
if(!len)
return sum == 0 ? 1 : 0;
if(sum < 0)
return 0;
if(!fp && dp[len][fixloc][sum] != -1)
return dp[len][fixloc][sum];
int fpmax = fp ? digit[len] : 9;
LL ret = 0;
for(int i=0;i<=fpmax;i++){
ret += dfs(len-1,fixloc,sum+i*(len-fixloc),fp && i == fpmax);
}
if(!fp)
dp[len][fixloc][sum] = ret;
return ret;
}
LL f(LL n)
{
if(n == -1)
return 0;
int len = 0;
while(n){
digit[++len] = n % 10;
n /= 10;
}
LL ret = 0;
for(int i=len;i>=1;i--){
ret += dfs(len,i,0,true);
}
return ret - len + 1;
}
int main()
{
memset(dp,-1,sizeof(dp));
int T;
LL a,b;
scanf("%d",&T);
while(T--)
{
scanf("%I64d%I64d",&a,&b);
printf("%I64d\n",f(b)-f(a-1));
}
return 0;
}