题目大意:若一个数以某个位置为支点,支点左右的加权和相同,这样的数被称为平衡数,求区间内平衡数的个数
思路:枚举支点位置,针对每个支点进行数位DP,但是0比较特殊,假设该数的长度为len,枚举len次支点位置,0会被重复计算len次,但我们只需要统计一次。
#include<stdio.h> #include<algorithm> #include<string.h> #include<stdlib.h> #include<iostream> using namespace std; #define LL long long #define INF 999999999 LL dp[20][20][5000]; int bit[20]; LL DFS(int pos,int k,int sum,int limit,int num) { if(pos < 0) { if(sum == 0) return 1; return 0; } if(!limit && dp[pos][k][sum]!=-1) return dp[pos][k][sum]; LL ans = 0; int len = limit?bit[pos]:9; for(int i=0;i<=len;i++) { int temp = sum + (pos-k)*i; ans += DFS(pos-1,k,temp,limit&&i==len,num*10+i); } if(!limit) dp[pos][k][sum] = ans; return ans; } LL Solve(LL n) { int pos = 0; LL ans = 0; while(n) { bit[pos++] = n%10; n/=10; } for(int k=0;k<pos;k++) { ans += DFS(pos-1,k,0,1,0); } return ans-pos+1; } int main() { int T; LL n,m; scanf("%d",&T); memset(dp,-1,sizeof(dp)); while(T--) { scanf("%I64d%I64d",&n,&m); LL ans = Solve(m) - Solve(n-1); printf("%I64d ",ans); } return 0; }