• 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
    ",so(r)-so(l-1));
        }
    }
    View Code
  • 相关阅读:
    hiho#1445 重复旋律5 求子串数量 后缀自动机
    SPOJ LCS2 后缀自动机
    SPOJ-LCS 后缀自动机
    bzoj 3261 最大异或和 可持久化字典树(01树)
    【洛谷1297】单选错位
    【HAOI2008】木棍分割
    【SDOI2016】排列计数
    【HAOI2008】下落的圆盘
    【HAOI2008】硬币购物
    【洛谷5520】青原樱
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/9919617.html
Copyright © 2020-2023  润新知