Atcoder beginner contest 336 -- E -- Digit Sum Divisible --- 题解(数位dp)

这篇具有很好参考价值的文章主要介绍了Atcoder beginner contest 336 -- E -- Digit Sum Divisible --- 题解(数位dp)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 

目录

 

E -- Digit Sum Divisibl

题目大意:

思路解析:

代码实现:


E -- Digit Sum Divisibl

题目大意:

给你一个整数n,让你找出小于等于n的数中一共有多少个好整数,并输出好整数的个数。对好整数的个数定义为如果一个数能被他的数位之和整除,则称这个数为好整数。例如 12 能被 3 整除。

n<=10^14。

思路解析:

看到数位之和,应该优先想到数位dp,那么我们想到最大的数位之和应该为14*9=126。则我们可以枚举每个数位之和k,看0-n中间是否有数位之和加起来刚好是k,并且刚好能被k整除。所以我们遍历次数为 126 * 10^14,这是不能接受的,但是对于每一个k来说,其实当中有许多重复遍历情况,所以可以用记忆化搜索来加速遍历行为。文章来源地址https://www.toymoban.com/news/detail-793140.html

代码实现:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.*;

public class Main {
    static int[] dig = new int[15];
    static long[][][] dp;
    static int p;
    public static void main(String[] args) throws IOException {
         Scanner input = new Scanner(System.in);
         long n = input.nextLong();
         dp = new long[15][127][127];
         p = 0;
         while (n > 0){
             dig[p++] =(int) (n % 10);
             n /= 10;
         }
         long res = 0;
        for (int k = 1; k <= 126; k++) {
            for (int i = 0; i < 15; i++) {
                for (int j = 0; j < 127; j++) {
                    Arrays.fill(dp[i][j], -1);
                }
            }
            res += dfs(p - 1, 0, 0, k, false);
        }
        System.out.println(res);
    }
    // lim 表示当前位是否有限制,如果lim == false,表示当前位选择没有限制,可以选择 0-9,否则只能选择0-dig[u]
    // u 表示当前抉择到哪一位了‘
    // s 表示抉择到当前位的数位之和为多少,
    // t表示当前数模上k后的余数是多少
    public static long dfs(int u, int s, int t, int k, boolean lim){
        if (u == -1 && t == 0 && s == k) return 1;
        if (u == -1) return 0;
        if (lim && dp[u][s][t] != -1) return dp[u][s][t];
        int x = lim ? 9 : dig[u];
        long ans = 0;
        for (int i = 0; i <= x; i++) {
            ans += dfs(u - 1, s+i, (t * 10 + i) % k, k, i != x || lim);
        }
        if (lim) dp[u][s][t] = ans;
        return ans;
    }
}

到了这里,关于Atcoder beginner contest 336 -- E -- Digit Sum Divisible --- 题解(数位dp)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • AtCoder Beginner Contest 317 题解 ABCDE | JorbanS

    题意 求权值和最大的一条路径 Tag dfs 题意 n × m n×m n × m 的迷宫, . 代表可以走, # 代表障碍物, ^v 代表射线,射线方向不能走,知道射线遇到非 . 的格子,求最短路 Tag bfs

    2024年02月10日
    浏览(35)
  • AtCoder Beginner Contest 302 H. Ball Collector 题解

    为了更好的阅读体验,请单击这里 AtCoder Beginner Contest 302 H. Ball Collector 题意跳过。 可以视作将 (a_i, b_i) 之间连了一条边,然后 (a_i, b_i) 之间只能选一个等价于对于一条边只能选择其一个端点。那么对于只包含树的联通块而言,如果都选择儿子节点,那么会有一个根节点无

    2024年02月06日
    浏览(39)
  • Atcoder Beginner Contest 324 G Generate Arrays 题解-Treap

    为了更好的阅读体验,请点击这里 题目链接 套上平衡树板子就能做的很快的题,然后因为是指针存树,因此交换只需要把序列大小较小的挨个拿出来插到相应的地方即可。复杂度 (O(N log^2 N)) 。 但是一定要记住 不可以直接使用 std::swap 交换包含带有指针的类的实例(如代码

    2024年02月08日
    浏览(44)
  • Atcoder Beginner Contest 324 F Beautiful Path 题解-分数规划

    为了更好的阅读体验,请点击这里 分数规划小技巧: 尽可能将式子写成存在某种取值,使得不等式成立的形式。 不然可能需要绕几个弯才能想出来。 题目链接 题目大意:给出一个 DAG,每条边有一个 (b_i, c_i) ,保证从编号小的边向编号大的边连边,且 (1) 到 (n) 必有路径

    2024年02月08日
    浏览(38)
  • AtCoder Beginner Contest 302 H. Ball Collector 题解 可撤销并查集

    为了更好的阅读体验,请单击这里 AtCoder Beginner Contest 302 H. Ball Collector 题意跳过。 可以视作将 (a_i, b_i) 之间连了一条边,然后 (a_i, b_i) 之间只能选一个等价于对于一条边只能选择其一个端点。那么对于只包含树的联通块而言,如果都选择儿子节点,那么会有一个根节点无

    2024年02月06日
    浏览(35)
  • Atcoder Beginner Contest 321 G - Electric Circuit 题解 - 状压dp | 指定最低位

    为了更好的阅读体验,请点击这里 题目链接:G - Electric Circuit 看到了 (N) 的数据范围,因此是显然的状压 dp。 不妨设 (f_S) 为仅使用 (S) 集合中的所有点,能够连成恰好 (1) 个连通块的方案数。 (g_S) 为仅使用 (S) 集合中的所有点的方案数,其中 (cntr(S)) 在 (S) 中为

    2024年02月05日
    浏览(54)
  • AtCoder Beginner Contest 310

    感觉F又双叒叕写复杂了 点杯咖啡,要 (p) 元,但可以用一个优惠券,使得咖啡只要 (q) 元,但你需要额外购买 (n) 个商品中(价格为 (a_i) )的一个。 问点杯咖啡的最小价格。 考虑直接买还是使用优惠券,使用优惠券的话就选 (n) 个商品中价格最小的。 两种情况取最小

    2024年02月16日
    浏览(28)
  • AtCoder Beginner Contest 320

    给定 (a,b) ,输出 (a^b + b^a) 。 因为数不超过 (10) ,可以直接用 pow 计算然后转成 (int) 。不会有精度损失。 神奇的代码 给定一个字符串 (s) ,求长度最长的回文串。 因为长度只有 (100) ,可以直接枚举子串,然后暴力判断是不是回文串(翻转后是否和自身相同),复杂

    2024年02月08日
    浏览(38)
  • AtCoder Beginner Contest 348

    给定 (n) ,输出 (ooxooxoox...) ,长度为 (n) 。 按题意模拟即可。 神奇的代码 给定 (n) 个点,对每个点,求出与其距离最远的点的下标。 (n) 只有 (100) ,对于每个点,花 (O(n)) 遍历每个点最大化距离,时间复杂度为 (O(n^2)) 。 神奇的代码 (n) 个豌豆,每个豌豆有美味值

    2024年04月08日
    浏览(42)
  • AtCoder Beginner Contest 300

    给定一个元素互不相同的数组 (c) 和 (a,b) ,找到 (i) 使得 (c_i = a + b) 直接 for 循环寻找即可。 神奇的代码 给定两个矩阵 (A,B) ,问能否对 (A) 进行若干次变换操作得到 (B) 。 变换分两种,一种是将第一列放到最后一列,另一种是将第一行放到最后一行。 范围不大,直

    2024年02月01日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包