题目链接:https://vjudge.net/contest/308832#problem/E
题目大意:
让你求一个区间的平衡数有多少个。平衡数:能找到一个对称轴,使两边的数平衡,例如:4139
以3为对称轴,左边:4 * 2+1 * 1=9, 右边:9 * 1=9, 左右相等,那么这个数平衡。
思路:直接枚举一下对称轴,然后数位dp。在不同的对称轴下0都是平衡数。其他数最多只能有一个对称轴。所以slove要减去在不同对称轴下多计算的0的个数。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
LL a[20];
LL dp[20][20][2000];
LL dfs(int pos, int s, int k, int mt)//s:左边-右边的值 k:对称轴
{
if(pos<k&&s<0)//可行性剪枝
{
return 0;
}
if(pos==-1)
{
if(s==0)//满足条件
{
return 1;
}
else
{
return 0;
}
}
if(!mt&&dp[k][pos][s]!=-1)
{
return dp[k][pos][s];
}
int Len=mt?a[pos]:9;
LL ans=0;
for(int i=0;i<=Len;i++)
{
if(pos>k)
{
ans+=dfs(pos-1, s+i*(pos-k), k, mt&&i==a[pos]);
}
if(pos<k)
{
ans+=dfs(pos-1, s-i*(k-pos), k, mt&&i==a[pos]);
}
if(pos==k)
{
ans+=dfs(pos-1, s, k, mt&&i==a[pos]);
}
}
if(!mt)
{
dp[k][pos][s]=ans;
}
return ans;
}
LL slove(LL x)
{
if(x<0)
{
return 0;
}
LL pos=0;
while(x)
{
a[pos++]=x%10;
x/=10;
}
LL ans=0;
for(int i=0;i<=pos-1;i++)
{
ans+=dfs(pos-1, 0, i, true);
}
return ans-pos+1;//减去多于的0
}
int main()
{
LL T, CUT=1;
memset(dp, -1, sizeof(dp));
scanf("%lld",&T);
while(T--)
{
LL L, R;
scanf("%lld%lld",&L,&R);
printf("%lld\n",slove(R)-slove(L-1));
}
return 0;
}