计数类 dp 可分为 计数 dp 和数位统计 dp。大多是用来统计方案数什么的,特别强调 不重不漏,在此还是根据各个题的特点将计数 dp 和数位 dp 分开整理。其实数位 dp 的题目会相对多很多…

计数dp 模板题

AcWing 900.整数划分

重点: 计数 dp、完全背包问题抽象

首先模拟下样例便于理解本题:

5 = 5
= 4 + 1
= 3 + 2
= 3 + 1 + 1
= 2 + 1 + 1 + 1
= 2 + 2 + 1
= 1 + 1 + 1 + 1 + 1
共七种划分方式

故我们可以将问题抽象为一个容量为 n 的背包,有 n 个体积为 1 ~ n 的物品,求恰好将该背包的方案数。每种物品可以使用无限次,故该问题是一个完全背包问题。

思路:

  • 状态定义:

    • f[i][j]:从 1~i 中选,且总体积恰好为 j 的选法数量
  • 状态转移:
    • 分类依据:根据最后一个物品选择个数进行状态划分,和完全背包问题的状态划分一致。

      • 第 i 个物品选 0 个:f[i-1][j]
      • 第 i 个物品选 1 个:f[i-1][j - i]
      • 第 i 个物品选 2 个:f[i-1][j - 2*i]
      • 第 i 个物品选 s 个:f[i-1][j - s*i]
    • 至此,朴素版完全背包问题就到此为止。但是,完全背包问题有一个非常厉害的优化方式。建议阅读:[背包] 背包问题算法模板(模板)
      • f[i][j] = f[i-1][j]+f[i-1][j-1]+f[i-1][j-i*2]+...+f[i-1][j-i*s]
      • f[i][j-i] = f[i-1][j-i]+f[i-1][j-i*2] +..+ f[i-1][j-i*s]
      • 仔细对比,发现 f[i][j-i] 和 f[i][j] 的后半段一样,故:
      • f[i][j] = f[i-1][j] + f[i][j-i]
    • 故状态转移方程为:f[i][j]=f[i-1][j]+f[i][j-i]
    • 和完全背包问题一样,也可以优化掉第一维,即 f[i]=f[j]+f[j-i]。体积从小到大循环即可
  • 状态初始化:f[0]=1,一个数都不选的方案是 1

完全背包代码:

const int mod = 1e9 + 7;
void solve() {
int n;
cin >> n;
int f[n + 1] = {1};
for (int i = 1; i <= n; ++i)
for (int j = i; j <= n; ++j)
f[j] = (f[j] + f[j - i]) % mod;
cout << f[n] << endl;
}

除了完全背包的写法及状态定义外,也有一种其它的状态定义方式,状态转移方程不同但是却能得到相同的结果…

思路:

  • 状态定义:

    • f[i][j] :所有总和是 i,并且恰好表示成 j 个数的和的方案的数量
  • 状态转移:
    • 分类依据:根据表示成的这 j 个数中是否包含 1,来进行集合划分

      • 如果包含 1,等价于 f[i-1][j-1],等价于和是 i-1 数量是 j-1 的选法数量
      • 如果每个数大于 1,则等价于将这 j 个数全部减去一个 1,则总数减去了 j,其和 f[i-j][j] 方案数相等。
    • 故状态转移方程 f[i][j] = f[i-1][j-1]+f[i-j][j]
    • 答案即为 ans = f[n][1] + f[n][2] +...+f[n][n]
  • 状态初始化f[0][0] = 1 代表总和是 0 的时候选 0 个的方案数是 1

代码:

const int mod = 1e9 + 7;
const int N = 1e3 + 10;
int f[N][N];
void solve() {
int n;
cin >> n, f[0][0] = 1;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= i; ++j)
f[i][j] = (f[i - 1][j - 1] + f[i - j][j]) % mod;
int ans = 0;
for (int i = 1; i <= n; ++i)ans = (ans + f[n][i]) % mod;
cout << ans << endl;
}

故可看出,同一个 dp 问题,不同的思考方式,不同的集合划分,不同的状态转移方程,只有思路是正确的,那么就是可行的。当然,在本题,划分方式不同导致了状态转移方程的不同,进而导致了求解答案时也不同。

参考

[计数dp] 整数划分(模板题+计数dp+完全背包变种题)的更多相关文章

  1. NYOJ90 整数划分(经典递归和dp)

    整数划分 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,  其中n1≥n2≥…≥nk≥1,k≥1.  正 ...

  2. HDU 1028 Ignatius and the Princess III dp整数划分

    http://acm.hdu.edu.cn/showproblem.php?pid=1028 dp[i][j]表示数值为i,然后最小拆分的那个数是j的时候的总和. 1 = 1 2 = 1 + 1 . ...

  3. 51nod 1201:整数划分 超级好的DP题目

    1201 整数划分 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  关注 将N分为若干个不同整数的和,有多少种不同的划分方式,例如:n = 6,{6} { ...

  4. HDU 5230 ZCC loves hacking 大数字的整数划分

    http://acm.hdu.edu.cn/showproblem.php?pid=5230 把题目简化后,就是求 1---n - 1这些数字中,将其进行整数划分,其中整数划分中不能有重复的数字,如果 ...

  5. HDU4632 Poj2955 括号匹配 整数划分 P1880 [NOI1995]石子合并 区间DP总结

    题意:给定一个字符串 输出回文子序列的个数    一个字符也算一个回文 很明显的区间dp  就是要往区间小的压缩! #include<bits/stdc++.h> using namesp ...

  6. 51nod 1201 整数划分 基础DP

    1201 整数划分  基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  关注 将N分为若干个不同整数的和,有多少种不同的划分方式,例如:n = 6,{6} ...

  7. hdu 5230 整数划分 dp

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5230 题意:给定n,c,l,r.求有多少种方法从1~n-1选取任意k数每个数的权重为其下标,使得这些数字之 ...

  8. 【noi 2.6_8787】数的划分(DP){附【转】整数划分的解题方法}

    题意:问把整数N分成K份的分法数.(与"放苹果"不同,在这题不可以有一份为空,但可以类比)解法:f[i][j]表示把i分成j份的方案数.f[i][j]=f[i-1][j-1](新开 ...

  9. 整数划分 (区间DP)

    整数划分(四) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 暑假来了,hrdv 又要留学校在参加ACM集训了,集训的生活非常Happy(ps:你懂得),可是他最近 ...

  10. 51nod 1201 整数划分 dp

    1201 整数划分 基准时间限制:1 秒 空间限制:131072 KB   收藏  关注 将N分为若干个不同整数的和,有多少种不同的划分方式,例如:n = 6,{6} {1,5} {2,4} {1,2 ...

随机推荐

  1. JavaWeb项目练习(学生选课管理系统)一

    打算做一个选课管理系统,作为期末的复习. 上需求 2.1 页面要求 (1)系统可以通过浏览器直接访问:(1分) (2)各个功能页面整体风格统一:(2分) (3)首页为用户登录页面,管理员.教师.学生三 ...

  2. [ABC318G] Typical Path Problem

    Problem Statement You are given a simple connected undirected graph $G$ with $N$ vertices and $M$ ed ...

  3. c标签的使用问题

    这是在使用c标签的时候遇到的问题,发现在导入包成功的情况下,jsp页面代码也没有问题.在网页上查了查,发现需要修改tomcat中的 conf/catalina.properties文件. 将tomca ...

  4. Git提交修正

    应用场景 日常开发中我们可能会遇到这样的问题 1.提交了代码有错误 2.提交的信息写错了 3.漏了一些文件没有提交 ...... 再或者我们写一个功能时,中间有很多小的提交,这中间就会产生特别多的co ...

  5. 51Nod - 1086 多重背包

    有N种物品,每种物品的数量为C1,C2......Cn.从中任选若干件放在容量为W的背包里,每种物品的体积为W1,W2......Wn(Wi为整数),与之相对应的价值为P1,P2......Pn(Pi ...

  6. 神经网络优化篇:详解梯度消失/梯度爆炸(Vanishing / Exploding gradients)

    梯度消失/梯度爆炸 训练神经网络,尤其是深度神经所面临的一个问题就是梯度消失或梯度爆炸,也就是训练神经网络的时候,导数或坡度有时会变得非常大,或者非常小,甚至于以指数方式变小,这加大了训练的难度. 接 ...

  7. CVE-2022-39197 复现

    CVE-2022-39197 ️漏洞介绍 Cobalt Strike (CS) 是一个为对手模拟和红队行动而设计的平台,相当于增强版的Armitage,早期以Metasploit为基础框架,3.0版本 ...

  8. 探索 Linux Namespace:Docker 隔离的神奇背后

    在 深入理解 Docker 核心原理:Namespace.Cgroups 和 Rootfs 一文中我们分析了 Docker 是由三大核心技术实现的. 今天就一起分析 Docker 三大核心技术之一的 ...

  9. zabbix-server 报错记录

    数据库磁盘满导至zabbix挂了 登陆zabbix页面提示错误信息,查看系统磁盘: /目录已满,导致mariadb数据库无法正常运行,如果有介质将会一直收取: 解决方法:扩容/目录,达到理想值,重启m ...

  10. ElasticSearch的简单api介绍

    1:ElasticSearch是什么? Elasticsearch 是一个分布式的免费开源搜索和分析引擎 适用于包括文本.数字.地理空间.结构化和非结构化数据等在内的所有类型的数据 Elasticse ...