“kuangbin带你飞”专题计划——专题十五 数位DP

目录

博客:

题目:

1.(题解传送门-待消化)Beautiful numbers CodeForces - 55D

2.【待完成】XHXJ's LIS HDU - 4352 :

3.(没有题解)不要62 HDU - 2089 :

4.(题解传送门-待消化!)Bomb HDU - 3555 :

5.(题解传送门)Round Numbers POJ - 3252 :

6.【题解传送门】Balanced Number HDU - 3709 :

7.(题解传送门-待消化)B-number HDU - 3652 :

8.(题解传送门-待总结)F(x) HDU - 4734 :

9.【待完成】BCD Code ZOJ - 3494 (数位DP+AC自动机):

10.(题解传送门)吉哥系列故事――恨7不成妻 HDU - 4507 :

11.(题解传送门)Balanced Numbers SPOJ - BALNUM :

平时训练遇到的数位DP

 1. 2021暑假牛客多校第一场F题(数位DP,好题)


写在前面:

这篇博客写的很随便,因为已经习惯了markdown,这种编辑方式真难受,水完了事,能看懂就行,排版就完全管了。

  • 开始时间:2021-06-07
  • 专题传送门:https://vjudge.net/article/187[kuangbin带你飞]专题1-23
  • 首次接触数位DP,可以先了解一下它的形式,然后变刷题边思考其原理,最后刷完这个专题之后再总结提炼一下它的思想

博客:

题目:

1.(题解传送门-待消化)Beautiful numbers CodeForces - 55D

  • 题意:给定两个数l,r(1<=l<=r<=9e18),求[l,r]间漂亮数的个数(漂亮数:能被所有非0数位整除的数)
  • 关键词:数位DP,模板

2.【待完成】XHXJ's LIS HDU - 4352

        1. 题意题解参考博客:hdu_4352_XHXJ's LIS(数位DP+状态压缩)

        2. 严格递增

3.(没有题解)不要62 HDU - 2089

  • 题意:统计区间 [a,b] 中不含 4 和 62 的数字有多少个。(0<a<=b<=1e6)
  • 题解:sb题,暴力

4.(题解传送门-待消化!)Bomb HDU - 3555

  • 题意:给一个数n(1<=n<=2^63-1),然后求出1~n中49子数和(比如49249=2,490302=1)
  • 关键词:数位DP,模板

5.(题解传送门)Round Numbers POJ - 3252

  • 关键词:数位DP,前导0的处理 

6.【题解传送门】Balanced Number HDU - 3709

  •  提示:枚举中心点
  • 关键词:枚举中心点,数位dp,好题

7.(题解传送门-待消化)B-number HDU - 3652 :

  • 题意:找出1~n有多少个数既含有13又能被13整除。(1<=n<=1e9)
  • 关键词:数位DP,模板,深搜DFS

8.(题解传送门-待总结)F(x) HDU - 4734

  • 题意:定义数 x=A_nA_{n-1}...A_2A_1 ,定义函数 F(x)=A_n*2^{n-1}+A_{n-1}*2^{n-2}+...+A_2*2+A_1*1,然后,给出一个区间 [A,B](0<=A,B<1e9),求区间 [0,B] 内满足F(i)<=F(A) 的 i 的个数。
    多组输入(T<=10000)。
  • 关键词:数位DP,模板题,数位DP总结1

9.【待完成】BCD Code ZOJ - 3494 (数位DP+AC自动机)

        1. 涉及AC自动机,等学字符串的时候再来看这里吧

        2. 题意参考:zoj 3494(ac自动机+数位dp)

        

10.(题解传送门)吉哥系列故事――恨7不成妻 HDU - 4507

  • 题意:多组输入T<=50,每个区间[L,R]。1<=L<=R<=1e18
  • 关键词:数位DP,dfs,进阶模板题
  • 收获&总结:

11.(题解传送门)Balanced Numbers SPOJ - BALNUM

  • 关键词:数位DP+好题+排除前置0的干扰!!!! 

平时训练遇到的数位DP

 1. 2021暑假牛客多校第一场F题(数位DP,好题)

  1. 题意:求[L,R]内的友好数的个数,(1<=L<=R<=1e18)。
    1. 友好数的定义:把这个数看作字符串,存在非空子串表示的数能被3整除,那么这个数为友好数,否则不为友好数。
    2. 带有前导0的子字符串被认为是合法的。
  2. 题解:数位DP。
  3. 一些提示(因为懒得梳理):
    1. 首先找dp数组,dp[pos][last0][last1][last2],last0,1,2分别表示以pos数结尾的上一位是否有0,1,2的余数。
    2. 最后判断一个数,如果没有前导0而且last0=0的时候既表示友好数
    3. 如果已经!lead的时候last0为1,那么后面的last0都为1
    4. 具体看代码。总之注意多方面思考
  4. 代码:
#include <bits/stdc++.h>
#define int long long
#define dbg(x) cout << #x << "===" << x << endl
using namespace std;

int l, r;
int dp[22][2][2][2];  // dp[pos][last0][last1][last2]
int t[5];
int a[22], cnt;
//前导0无影响
int dfs(int pos, int k0, int k1, int k2, bool lead, bool limit) {
    if (pos == -1) return k0 && (!lead);
    if (!limit && !lead && dp[pos][k0][k1][k2] != -1)
        return dp[pos][k0][k1][k2];
    int res = 0;
    int up = limit ? a[pos] : 9;
    for (int i = 0; i <= up; i++) {
        t[0] = t[1] = t[2] = 0;
        t[(0 * 10 + i) % 3] = 1;
        if (k1) t[(1 * 10 + i) % 3] = 1;
        if (k2) t[(2 * 10 + i) % 3] = 1;
        if (!lead && k0) t[0] = 1;
        res += dfs(pos - 1, t[0], t[1], t[2], lead && (i == 0),
                   limit && (i == a[pos]));
    }
    if (!lead && !limit) dp[pos][k0][k1][k2] = res;
    return res;
}
int solve(int x) {
    cnt = 0;
    while (x) {
        a[cnt++] = x % 10;
        x /= 10;
    }
    return dfs(cnt - 1, 0, 0, 0, true, true);
}

signed main() {
    int T;
    cin >> T;
    memset(dp, -1, sizeof(dp));
    while (T--) {
        cin >> l >> r;
        // dbg(solve(r));
        // dbg(solve(l - 1));
        int ans = solve(r) - solve(l - 1);
        // cout << ">>>>";
        cout << ans << endl;
    }
    return 0;
}

某次任务——数位dp分享

1. 收获很多啊。果然将知识讲出来效果最好。

总结:1.1 把数位DP整个过程看作遍历一棵树的过程。

1.2 dp[][]表示的是树上某一个节点能到达的满足条件的叶子节点的数。

1.3 从暴力到数位dp优化的是树上结点的数目,我们把同一层的点权相同的节点合并。

2. 详见我的ppt: 数位dp——某次队内分享任务

3. 理解这一颗树的过程:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值