• HDU3709 Balanced Number 题解 数位DP


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3709

    题目大意:
    求区间 ([x, y]) 范围内“平衡数”的数量。

    所谓平衡数是指:以某一位为支点,它左边的所有位的数乘以它到支点的距离之和等于它右边的所有位的数乘以它到支点的距离之和。
    比如, (4139) 是平衡数,因为以 (3) 为支点,

    • 左边的每一位数与距离的乘积和为 (4 imes 2 + 1 imes 1 = 9)
    • 右边的每一位数与距离的乘积和为 (9 imes 1 = 9)

    所以左右两边的数与距离的乘积和是相等的,所以 (4139) 是一个平衡数。

    问题分析:
    对于这道题,我们需要先枚举支点在哪一位,
    然后,在确定支点所在的位的基础上,进行 数位DP
    我们设状态 (f[cid][pos][delta]) 表示:

    • 枚举的支点在第 (cid) 位,
    • 当前所处的数位为 (pos)
    • (delta) 为从最高位到第 (pos + 1) 位的每一位上的数字 (num_i) 与其与 (col) 位的距离的乘积和 (sum num_i imes (i-col))

    然后我们开函数 dfs(int cid, int pos, int delta, bool limit),其中:

    • cidposdelta的含义同上;
    • limit 表示当前是否处于限制状态。

    只要 pos<0delta==0 则找到一种情况。

    注意:因为枚举每一位 col 时,数字 (0) 的情况都会计算上去,所以需要在枚举每一位是都减去 (0) 的情况,最后再加上 (0) 的情况。

    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    long long f[20][20][1800], a[20];
    void init() {
        memset(f, -1, sizeof(f));
    }
    long long dfs(int cid, int pos, int delta, bool limit) {
        if (pos < 0) return !delta;
        if (!limit && f[cid][pos][delta] != -1) return f[cid][pos][delta];
        int up = limit ? a[pos] : 9;
        long long tmp = 0;
        for (int i = 0; i <= up; i ++) {
            int d = delta + (pos-cid)*i;
            if (d < 0) continue;
            tmp += dfs(cid, pos-1, d, limit && i==up);
        }
        if (!limit) f[cid][pos][delta] = tmp;
        return tmp;
    }
    long long get_num(long long x) {
        if (x < 0) return 0;
        int pos = 0;
        long long res = 0;
        while (x) {
            a[pos++] = x % 10;
            x /= 10;
        }
        for (int cid = 0; cid < pos; cid ++) {
            res += dfs(cid, pos-1, 0, true);
            res -= 1; // 减去0的情况
        }
        return res + 1; // 加上0的情况
    }
    int T;
    long long x, y;
    int main() {
        init();
        scanf("%d", &T);
        while (T --) {
            scanf("%lld%lld", &x, &y);
            printf("%lld
    ", get_num(y) - get_num(x-1));
        }
        return 0;
    }
    
  • 相关阅读:
    vue异步组件
    vue-awesome-swiper的使用
    自定义button组件时slot的使用
    axios拦截器的简单使用
    vue静态类名和动态类名绑定的几种方式
    快速知道所有元素的边框
    【转】CICD工具
    mocha学习(四)为项目开发一个BDD测试
    mocha学习(三)hook 机制 和 测试技巧
    mocha学习(二)mocha接口
  • 原文地址:https://www.cnblogs.com/quanjun/p/11973344.html
Copyright © 2020-2023  润新知