当前位置: 首页 > web >正文

数位DP -

算法概述

什么是数位DP:

数位DP往往都是这样的题型,给定一个闭区间[L,R]让你求这个区间中满足某种条件的数的总数。所谓数位dp,就是对数位进行dp,也就是个位、十位等

时间复杂度:O(logN)        

常用流程:

例题1:windy数

link:P2657 [SCOI2009] windy 数 - 洛谷

推荐题解(特别详细,强烈推荐):题解 P2657 【[SCOI2009]windy数】 - 洛谷专栏

code

#include "bits/stdc++.h"
using namespace std;
using ll = long long;
ll dp[15][10];//dp[i][j]:长度为i的最高位为j的所有数字对应的windy数数目
// 当j==0: dp[i][0] == dp[i-1][2] + dp[i-1][3] + ... + dp[i-1][9];ll work(ll n)// return [0, n)中的windy数,注意不包括n
{int a[15] = { 0 };int len = 0;while (n){a[++len] = n % 10;n /= 10;}ll ans = 0;// 若 n = 54321// 计算windy(0~9999), 不能直接ans+=dp[len][0],因为题目要求不算前导0,dp[len][0]中不包含dp[len - 1][1]与dp[len-1][0]for (int i = 1; i <= len - 1; i++)for (int j = 1; j <= 9; j++)ans += dp[i][j];// windy(10000~49999)for (int i = 1; i <= a[len] - 1; i++) ans += dp[len][i];// windy(50000~54321)for (int i = len - 1; i >= 1; i--){for (int j = 0; j < a[i]; j++)// 因不包含最后a[i],work(n)求的是windy([0, n)),左闭右开,即不包括n{if (abs(j - a[i + 1]) >= 2) ans += dp[i][j];}if (abs(a[i] - a[i + 1]) < 2) break;}return ans;
}void init()
{for (int i = 0; i <= 9; i++)dp[1][i] = 1;for (int len = 2; len <= 11; len++){for (int i = 0; i <= 9; i++){for (int k = 0; k <= 9; k++){if(abs(i-k) >= 2) dp[len][i] += dp[len - 1][k];}}}
}int main()
{ll a, b; cin >> a >> b;init();ll ans = work(b + 1) - work(a);// 只考虑上界cout << ans << endl;return 0;
}

例2:7的意志

link:7的意志

code

#include "bits/stdc++.h"
using namespace std;
using ll = long long;
int dig[20];
ll dp[20][10][10];// dp[len][sum%7][sum1%7]:所有的长度为len的...ll dfs(int pos, int sum, int sum1, int limit)// return 前pos数对应的7的意志数,如n=54321, pos = 2,则dfs return[0, 54]中7的意志数
{if (pos == 0) return sum1 == 0 && sum == 0;if (!limit && dp[pos][sum][sum1] != -1) return dp[pos][sum][sum1];// limit为false才可使用通用dpll res = 0;ll up = limit ? dig[pos] : 9;for (int i = 0; i <= up; i++){res += dfs(pos - 1, (sum * 10 + i) % 7, (sum1 + i) % 7, limit && (i == dig[pos]));}if(!limit)dp[pos][sum][sum1] = res;// (!limit意味着up为9,此时的dp[pos]具有通用性return res;
}ll work(ll n)// 计算[0, n]7的意志的个数
{ll len = 0;while (n){dig[++len] = n % 10;n /= 10;}memset(dp, -1, sizeof dp);return dfs(len, 0, 0, 1);
}int main()
{ll n, m; while (true){cin >> n >> m; if (n == 0 && m == 0)return 0;ll ans = work(m) - work(n - 1);cout << ans << endl;}
}

http://www.xdnf.cn/news/20450.html

相关文章:

  • 【明道云】[工作表控件11] 地理位置控件与地图定位应用
  • 用内存顺序实现 三种内存顺序模型
  • 安装es和kibana
  • Linux之Firewalld防火墙实战篇
  • [光学原理与应用-435]:晶体光学 - 晶体的结构-基元/原胞/晶胞/点阵
  • 多次base64编码过滤垃圾字符
  • 讲一下模版特化和偏特化的区别
  • 如何在Kali Linux官网下载历史版本
  • Redis 持久化机制:AOF 日志深度解析
  • Hystrix与Sentinel-熔断限流
  • 创建阿里云ECS实例操作(免费试用版)
  • 【C++】模板和STL
  • Unity的UGUI更改背景以及添加中文字体
  • 【FastDDS】XML profiles
  • AI助力特征工程:智能化数据科学新范式
  • leetcode 912 排序数组
  • 微前端框架性能对比与选型指南:从理论到实践
  • Redis 的三种高效缓存读写策略!
  • 从技术架构、接入路径、应用场景全梳理的智慧地产开源了
  • C++ 并发编程指南 并发设计模式:Actor vs. CSP (生活场景版)
  • [Upscayl图像增强] Electron主进程命令 | 进程间通信IPC
  • Django 项目6:表单与认证系统
  • PostgreSQL与Greenplum数据库的编程语言连接
  • 深入理解 RequestContextHolder、ThreadLocal 与 RequestContextFilter
  • Spring 基于注解的自动化事务
  • JBoltAI:解锁企业AI数智化升级的Java利器
  • 算法与数据结构实战技巧:从复杂度分析到数学优化
  • 13-Java-面向对象-封装和this关键字
  • Jenkins运维之路(自动获得分支tag自动构建)
  • ComfyUI Easy - Use:简化ComfyUI操作的得力插件