您的位置:首页 > 其它

hdu 3709 Balanced Number 数位dp

2015-12-10 17:50 134 查看
题目链接

一个数称为平衡数, 只要他的某一位满足, 这一位左边的所有数sigma x*(x距离这一位的距离)等于右边的sigma x*(x距离这一位的距离), 例如4139, 3就满足这个性质, 因为4*2+1*1 == 9*1。

求出一个范围内的平衡数的数量。

看起来好麻烦, 不好想状态, 但是我们可以枚举每一位作为支点, 这样问题就简化了许多。具体看代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mem1(a) memset(a, -1, sizeof(a))
ll dp[20][20][4000], digit[20];
ll dfs(int len, int center, int sum, bool fp) {
if(!len) {
return sum==0;
}
if(!fp&&dp[len][center][sum]!=-1)           //center是支点, sum是和
return dp[len][center][sum];
ll maxx = fp?digit[len]:9, ret = 0;
for(int i = 0; i<=maxx; i++) {
ret += dfs(len-1, center, sum+i*(center-len), fp&&i==maxx);
}
if(!fp)
return dp[len][center][sum] = ret;
return ret;
}
ll cal(ll n) {
int len = 0;
while(n) {
digit[++len] = n%10;
n/=10;
}
ll ret = 0;
for(int i = 1; i<=len; i++) {
ret += dfs(len, i, 0, 1);           //枚举每一位
}
return ret-(len-1);         //因为每次计算了len个0, 而我们只需要一个0
}
int main()
{
ll a, b, t;
mem1(dp);
cin>>t;
while(t--) {
scanf("%I64d%I64d", &a, &b);
printf("%I64d\n", cal(b)-cal(a-1));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: