博客
关于我
【总结】数位dp
阅读量:177 次
发布时间:2019-02-28

本文共 2594 字,大约阅读时间需要 8 分钟。

数位动态规划(Digit DP)是一种强大的技术,可以用来解决涉及数位操作的问题。它通过将问题分解为较小的子问题,并在每一步中记录必要的状态信息,来逐步解决整个问题。在本文中,我将详细探讨如何使用数位动态规划来计算满足特定条件的数的平方和。

数位动态规划的基本概念

数位动态规划的核心思想是将一个大数分解为各个数位,并在每一步中选择一个数位上的数字,逐步构建满足条件的数。为了记录状态信息,我们通常使用以下变量:

  • 位置(pos):表示当前处理的数位位置。
  • 前导零(leading_zero):表示是否当前数的前面有零。
  • 限制条件(tight):表示是否当前数的数位已经达到最大允许值。
  • 余数状态(mod):记录当前数在模运算下的余数。
  • 满足条件的数的个数(count):记录满足特定条件的数的个数。
  • 满足条件的数的和(sum):记录满足条件的数的和。
  • 满足条件的数的平方和(sum_sq):记录满足条件的数的平方和。
  • 状态转移方程

    在每一步中,我们选择一个数位上的数字 ( d ),并更新状态变量:

    • 位置:递减1。
    • 前导零:如果当前数位是0且前面没有非零数字,则仍为真。
    • 限制条件:如果当前数位选择了最大允许值,则限制条件变为真。
    • 余数状态:更新为当前数位数字 ( d ) 加上上一步的余数乘以10的结果,再模上模数。
    • 满足条件的数的个数、和、平方和:根据新选择的数字,递归地更新这些值。

    代码实现

    下面是一个使用 C++ 编写的数位动态规划代码示例,用于计算满足特定条件的数的平方和:

    #include 
    using namespace std;const int MOD = 1e9 + 7;struct Number { int num, nc, nc2, vis;};int f[20][7][7];int a[20], len;int solve(int x) { len = 0; while (x) { a[++len] = x % 10; x /= 10; } return dfs(len, 0, 0, 1).nc2;}int fpow(int x, int y) { int tot = 1; for (; y > 0; y >>= 1) { if (y & 1) { tot = (tot * x) % MOD; } x = (x * x) % MOD; } return tot;}Number dfs(int x, int y, int z, int limit) { if (x == 0) { if (y && z) { f[x][y][z].num = 1; } return f[x][y][z]; } if (!limit && f[x][y][z].vis != 0) { return f[x][y][z]; } int maxn = (limit == 1 ? a[x] : 9); Number u = Number(); for (int i = 0; i <= maxn; ++i) { if (i == 7) continue; Number v = dfs(x - 1, (y + i) % 7, (z * 10 + i) % 7, limit && (i == a[x])); u.num = (u.num + v.num) % MOD; u.nc = (u.nc + v.nc + fpow(10, x - 1) * i * v.num % MOD) % MOD; u.nc2 = (u.nc2 + v.nc2 + 2 * i * fpow(10, x - 1) % MOD * v.nc % MOD + fpow(10, 2 * (x - 1)) * i * i % MOD * v.num % MOD) % MOD; } if (!limit) { f[x][y][z] = u; f[x][y][z].vis = 1; } return u;}int solve() { len = 0; while (true) { char c = getchar(); if (c < '0' || c > '9') break; } while (c >= '0' && c <= '9') { a[++len] = c - '0'; c = getchar(); } reverse(a + 1, a + 1 + len); return dfs(len, 0, 0, 1).nc2;}int main() { int T; cin >> T; while (T--) { cin >> n >> m; int res = (solve(m) - solve(n - 1) + MOD) % MOD; cout << res << endl; }}

    代码解释

  • 结构体 Number:用于存储当前数的个数、和、平方和以及是否被访问过。
  • 递归函数 dfs:处理递归,根据当前数位选择数字并更新状态。
  • 前缀处理函数 fpow:计算10的幂次,用于平方和的计算。
  • 求解函数 solve:处理输入并调用递归函数,返回结果。
  • 应用示例

    假设我们需要计算满足某些模数条件的数的平方和,可以通过上述代码进行调整。例如,在 solve 函数中,根据具体需求修改模数和条件。

    总结

    数位动态规划是一种强大的工具,可以用来解决涉及数位操作的问题。通过设计合适的状态变量和转移方程,我们可以高效地计算满足特定条件的数的平方和。对于更复杂的需求,可以通过扩展状态变量和增加转移条件来解决。

    转载地址:http://eown.baihongyu.com/

    你可能感兴趣的文章
    Open-Source Service Discovery
    查看>>
    open-vm-tools-dkms : 依赖: open-vm-tools (>= 2:9.4.0-1280544-5ubuntu3) 但是它将不会被安装
    查看>>
    open3d-Dll缺失,未找到指定模块解决
    查看>>
    openai Midjourney代理服务 gpt大模型第三方api平台汇总 支持国内外各种大模型 持续更新中...
    查看>>
    OpenAll:Android打开组件新姿势【仅供用于学习了解ButterKnife框架基本原理】
    查看>>
    OpenASR 项目使用教程
    查看>>
    Openbox-桌面图标设置
    查看>>
    opencart出现no such file or dictionary
    查看>>
    OpenCV 3.1 imwrite()函数写入异常问题解决方法
    查看>>
    OpenCV 4.1.0版drawContours
    查看>>
    opencv glob 内存溢出异常
    查看>>
    opencv Hog Demo
    查看>>
    opencv Hog学习总结
    查看>>
    opencv Mat push_back
    查看>>
    opencv putText中文乱码
    查看>>
    OpenCV Python围绕特定点将图像旋转X度
    查看>>
    opencv resize
    查看>>
    opencv SVM分类Demo
    查看>>
    OpenCV VideoCapture.get()参数详解
    查看>>
    opencv videocapture读取视频cap.isOpened 输出总是false
    查看>>