• HDU 3709 Balanced Number 数位dp


    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=3709

    Balanced Number

    Time Limit: 10000/5000 MS (Java/Others)
    Memory Limit: 65535/65535 K (Java/Others)
    #### 问题描述 > A balanced number is a non-negative integer that can be balanced if a pivot is placed at some digit. More specifically, imagine each digit as a box with weight indicated by the digit. When a pivot is placed at some digit of the number, the distance from a digit to the pivot is the offset between it and the pivot. Then the torques of left part and right part can be calculated. It is balanced if they are the same. A balanced number must be balanced with the pivot at some of its digits. For example, 4139 is a balanced number with pivot fixed at 3. The torqueses are 4*2 + 1*1 = 9 and 9*1 = 9, for left part and right part, respectively. It's your job > to calculate the number of balanced numbers in a given range [x, y]. #### 输入 > The input contains multiple test cases. The first line is the total number of cases T (0 < T ≤ 30). For each case, there are two integers separated by a space in a line, x and y. (0 ≤ x ≤ y ≤ 1018). #### 输出 > For each case, print the number of balanced numbers in the range [x, y] in a line. ####样例输入 > 2 > 0 9 > 7604 24324

    样例输出

    10
    897

    题意

    求区间[L,R]内的一类平衡数,平衡数定义:存在一个数位,它两侧的力矩想等。 比如4139,存在数位3,有4*2+1*1=9*1

    题解

    数位dp,这题如果状态想对的话非常好写。
    dp[i][j][sum]表示支点为j,前i位力矩和为sum的情况数。

    特性:对于大于0的平衡数,支点有且只有一个,且如果考虑相对于支点的位差为每一位位权,所有位权和为0,如:4139有sum=4*2+1*1+3*0+9*(-1)=0

    代码

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<functional>
    using namespace std;
    #define X first
    #define Y second
    #define mkp make_pair
    #define lson (o<<1)
    #define rson ((o<<1)|1)
    #define mid (l+(r-l)/2)
    #define sz() size()
    #define pb(v) push_back(v)
    #define all(o) (o).begin(),(o).end()
    #define clr(a,v) memset(a,v,sizeof(a))
    #define bug(a) cout<<#a<<" = "<<a<<endl
    #define rep(i,a,b) for(int i=a;i<(b);i++)
    #define scf scanf
    #define prf printf
    
    typedef __int64 LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<pair<int,int> > VPII;
    
    const int INF=0x3f3f3f3f;
    const LL INFL=0x3f3f3f3f3f3f3f3fLL;
    const double eps=1e-8;
    const double PI = acos(-1.0);
    
    //start----------------------------------------------------------------------
    
    const int maxn=22;
    
    int arr[maxn],tot;
    
    LL dp[maxn][maxn][1805];
    ///ismax标记表示前驱是否是边界值
    LL dfs(int len,int j, int sum,bool ismax) {
        if(sum<0) return 0;
        if (len == 0) {
            if(sum==0) return 1;
            else return 0;
        }
        if (!ismax&&dp[len][j][sum]>=0) return dp[len][j][sum];
        LL res = 0;
        int ed = ismax ? arr[len] : 9;
    
        ///这里插入递推公式
        for (int i = 0; i <= ed; i++) {
            res += dfs(len - 1, j, sum+(len-j)*i,ismax&&i == ed);
        }
        return ismax ? res : dp[len][j][sum] = res;
    }
    
    LL solve(LL x) {
        tot = 0;
        while (x) { arr[++tot] = x % 10; x /= 10; }
    
        LL ret=0;
        for(int j=1;j<=tot;j++){
            ret+=dfs(tot,j,0,true)-1;
        }
    
        return ret+1;
    }
    
    int main() {
        clr(dp,-1);
        int tc;
        scf("%d",&tc);
        while(tc--){
            LL x,y;
            scf("%I64d%I64d",&x,&y);
            LL ans;
            if(x>0) ans=solve(y)-solve(x-1);
            else ans=solve(y);
            prf("%I64d
    ",ans);
        }
        return 0;
    }
    
    //end-----------------------------------------------------------------------
    

    Notes

    这题关键的支点的性质想到了,但是状态少想了一个,发现很难转移,对于dp这种东西,如果时间,空间允许,状态越高维,问题应该会相对越好转移。

    要发现引起你状态无法转移的变量,然后把它作为定值去枚举它!!!!!!!!!!!!!!!!!!

  • 相关阅读:
    Mac环境下svn的使用
    开发中常见问题集锦
    【C语言】07基本语句和运算
    【C语言】05printf和scanf函数
    【C语言】03第一个C程序代码分析
    【C语言】06基本数据类型
    【C语言】04函数
    【C语言】01C语言概述
    让UIWebView弹出键盘上的按钮显示中文
    【C语言】02第一个C程序
  • 原文地址:https://www.cnblogs.com/fenice/p/5888647.html
Copyright © 2020-2023  润新知