HDU 3709 Balanced Number 求区间内的满足是否平衡的数量 (数位dp)

平衡数的定义是指,以某位作为支点,此位的左面(数字 * 距离)之和 与右边相等,距离是指某位到支点的距离;

题意:求区间内满足平衡数的数量 ; 

分析:很好这又是常见的数位dp , 不过不同的是我们这次需要枚举是哪个位置是平衡点 , 一开始我是想说搜索到最后以为 ,然后得到这个数的位数 ,在判断平衡位置 , 想到这样的话 , 这就说明了我对数位dp 还是不太熟悉的 ,因为这样的话dfs() 里面的sum , emmm是找不到状态的 ;

正解: 依然是枚举平衡点的位置  ,这个思路没有问题 , 但是这个却是在so(_) 函数里面枚举 ,啊这样就妙不可言了, 这样的话只要我们在dfs()里面增加变量 k ,表示是平衡点的位置 , 那这样的话我的sum 就是记录 从左到右的贡献 , 因为是从左到右的枚举 , 左边加, 右边减 , 所以是不是sum<0 , 就肯定是不行的嘛 ;哦!还有一个重点 ,因为0也是平衡数来的 , 所以我们这样的枚举平衡点就加了ans-1 次0 的贡献 ,这里巨坑一开始没有想到,其他代码打出来了 , 答案不对 ,然后找程序的错误 ,其实这里是关键来的

#include<stdio.h>
#include<string.h>
#include<cmath>
using namespace std ;
#define ll long long
ll dp[20][20][2002];
ll a[20];
ll dfs(int pos , int k , int  sum , bool limit)
{
    if(pos==-1)
    return sum==0;
    if(sum<0)
    return 0;
    if(!limit && dp[pos][k][sum]!=-1)
    return dp[pos][k][sum];
    int up=limit?a[pos]:9;
    ll ans=0;
    for(int i=0 ; i<=up ; i++)
    {
        ans+=dfs(pos-1,k,sum+(pos-k)*i,limit&&i==a[pos]);
    }
    if(!limit)
    dp[pos][k][sum]=ans;
    return ans;
}
ll so(ll x)
{
    int ans=0;
    ll sum=0;
    while(x)
    {
        a[ans++]=x%10;
        x/=10;

    }
    for(ll i=0 ; i<ans ; i++)
    sum+=dfs(ans-1,i,0,1);
    return sum-(ans-1);
}
int  main( )
{

    int  t;
    memset(dp,-1,sizeof(dp));
    scanf("%d",&t);
    while(t--)
    {
        ll  l,r;
        scanf("%lld%lld",&l,&r);
        printf("%lld\n",so(r)-so(l-1));
    }
}
View Code

 

posted @ 2018-11-06 23:17  shuai_hui  阅读(210)  评论(0编辑  收藏  举报