题意:一个数选定自身的一位为中轴,这个中轴左边的每位*该位与中轴的距离=右边的每位*该位与中轴的距离。举个例子:4139选定3为中轴,那么左边的和为4*2+1*1=9,右边为9*1=9,左右相等,所以是平衡数。问a~b有多少个平衡数。
题解:
1.dp[i][j][k]表示i位数、pivox位于第j位、和为k的个数。
2.枚举中轴pivox的位置进行套路记忆化搜索即可。
3.重点是需要去重,因为每个数最多只有1个满足题意的中轴,所以不会重复。但是枚举时会产生0,00,000...这样的数,所以需要减去多余的0。
4.注意边界问题,即查询0和1时,细节在代码注释中。
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
long long dp[20][20][5005] ; //dp[i][j][k]表示i位数 pivot位于第j位 和为k的个数
int bit[50] ;
long long dfs(int len , int pivox , int sum , int lim)
{
int i , j , k ;
int num ;
long long ans = 0 ;
int sum1 ;
if(len == 0)
return sum == 0 ;
if(sum < 0)
return 0 ;
if(!lim && dp[len][pivox][sum] != -1)
return dp[len][pivox][sum] ;
if(lim)
num = bit[len] ;
else
num = 9 ;
for(i = 0 ; i <= num ; i ++)
ans += dfs(len - 1 , pivox , sum + i * (len - pivox) , lim && i == num) ;
if(!lim)//若没有上限,则可以记录答案,防止重复计算
dp[len][pivox][sum] = ans ;
return ans ;
}
long long count(long long a)
{
int i ;
int len = 0 ;
long long ans = 0 ;
if(a <= 0) // 注意边界问题
return a + 1 ;
while(a)
{
bit[++len] = a % 10 ;
a /= 10 ;
}
for(i = 1 ; i <= len ; i ++)
ans += dfs(len , i , 0 , 1) ;
return ans - (len - 1) ;
}
int main()
{
long long a , b ;
int t ;
long long ans , ans1 , ans2 ;
int i ;
memset(dp , -1 , sizeof(dp)) ;
scanf("%d" , &t) ;
while(t --)
{
scanf("%lld%lld" , &a , &b) ;
ans1 = count(b) ;
ans2 = count(a - 1) ;
ans = ans1 - ans2 ;
printf("%lld\n" , ans) ;
}
}