题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3709
题目大意:
对于一个数,把每一位的数字当作这一位的重量。若在某个数位上放一个支点,力矩能够达到平衡,则称这个数为”平衡数“。
如4139就是一个"平衡数",若在3的位置放一个支点,则4*2 + 1*1 = 9 且 9*1 = 9。
算法:
我是从高位向低位处理的,
这道题需要记录的有两个量,
第一是支点在哪个位(从个位数起),二是当前已经处理的力矩和是多少。
根据支点的位置,直接可以通过相对距离算出当前数位的力矩,与其它变量均无关。
开数据组时需注意,力矩能够达到的最大值为17*(17+1)/2*9=1377。
另外,与一般题目不同,这道题中0也是符合要求的。
但是我懒得改变自己习惯的写法。
所以对于非零数,我计数的初始值就为1,这是因为0也是“平衡数”,但我的函数是不考虑0的。
代码如下:
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
using namespace std;
int dig[30];
long long d[2][20][20][2000];
long long dp(bool less, bool fst, int pos, int p, int tmp)
{
if(pos==-1)
{
return less&&(tmp==0);
}
if(less&&d[fst][pos][p][tmp]!=-1)
{
return d[fst][pos][p][tmp];
}
long long ret=0LL;
for(int i=0; i<10; i++)
{
if((!less)&&i>dig[pos])
{
continue;
}
if(fst&&!i)
{
continue;
}
if((tmp+i*(pos-p))<0)
{
continue;
}
ret+=dp(less||i<dig[pos],false,pos-1,p,tmp+i*(pos-p));
}
if(less)
{
d[fst][pos][p][tmp]=ret;
}
return ret;
}
long long solve(long long x)
{
if(x==0)
{
return 0LL;
}
int tot=0;
while(x)
{
dig[tot++]=x%10;
x/=10;
}
long long ret=1LL;
for(int i=0; i<tot; i++)
{
for(int j=0; j<=i; j++)
{
ret+=dp(i<tot-1,true,i,j,0);
}
}
return ret;
}
int main()
{
int cas;
memset(d,-1,sizeof(d));
scanf("%d",&cas);
while(cas--)
{
long long a,b;
scanf("%I64d%I64d",&a,&b);
printf("%I64d\n",solve(b+1)-solve(a));
}
return 0;
}