string - 求一个 n 位数字中能被 8 整除的子序列的个数

标签 string algorithm time-complexity dynamic-programming combinatorics

给定 n = 1 到 10^5,以十进制格式存储为字符串。

示例:如果 n = 968,则在所有子序列(9、6、8、96、68、98、968)中,有 3 个子序列(即 968、96 和 8)可被 8 整除.所以,答案是3。

由于答案可能非常大,因此打印答案模 (10^9 + 7)。

最佳答案

您可以使用动态规划。令 f(len, sum) 为长度为 len 的前缀的子序列数,其总和为 sum 模 8 ( >sum 范围从 0 到 7)。

对于 len = 1f 的值是显而易见的。转换过程如下:

  1. 我们可以在新位置开始一个新的子序列:f(len, a[i] % 8) += 1

  2. 我们可以从较短的前缀继续任何子序列:

    for old_sum = 0..7
         f(len, (old_sum * 10 + a[i]) % 8) += f(len - 1, old_sum) // take the new element
         f(len, old_sum) += f(len - 1, old_sum) // ignore the new element
    

当然,您可以执行所有计算模块 10^9 + 7 并使用标准整数类型。

  • 答案是 f(n, 0)(考虑所有元素,模 8 的总和为 0)。
  • 此解决方案的时间复杂度为 O(n)(因为有 O(n) 状态,并且每个状态有 2 个转换)。

    注意:如果数字不能有前导零,则可以为状态添加一个参数:一个标志,指示子序列的第一个元素是否为零(该序列不应扩展)。解决方案的其余部分保持不变。

    关于string - 求一个 n 位数字中能被 8 整除的子序列的个数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41597061/

    相关文章:

    Python:通过附加现有列表中的信息来创建新元组

    algorithm - 最后剩余号码

    algorithm - 给定输入和时间的时间复杂度

    c# - C# 中 foreach() 的复杂性。网

    python - 操作包含数字的字符串列表以输出数字列表

    php - 用于从数组中 checkin 字符串的八进制

    java - 删除标点符号,保留字母和空格 - Java Regex

    arrays - 用不同维度的项目填充包的算法逻辑

    c++ - 欧拉计划挑战 3 : Finding the largest prime factor of a large number

    c# - 从 C# 编码 "as string"参数