前言

如果你对这篇文章可感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。

划分数概述

一、适用问题

只要涉及一些难以用组合公式直接求得的数的划分问题。比如将 nnn 个数划分成多个不大于 mmm 的划分方法,且不存在相同数。或者划分成若干奇数或偶数的问题。

划分要求千变万化,主要识别点在于将划分数类比为盒子与球的问题,类比成多个球放到多个盒子中,且球和盒子都没有区别。

这类问题与一般的划分问题都不同,需要二维 dpdpdp 求解,有时还需要处理前缀和进行计算。

二、算法举例

1.将 nnn 个数划分成多个不大于 mmm 的数,可以存在相同整数

f[n][m]f[n][m]f[n][m] 表示整数 nnn 的划分中,每个数都不大于 mmm 的划分方案。转移时可以分成两种情况,第一种情况,划分方案中每个数都小于 mmm,因此划分方案为 f[n][m−1]f[n][m-1]f[n][m−1]。

第二种情况,划分方案中至少有一个数为 mmm,即在 nnn 中减去 mmm,得到 f[n−m][m]f[n-m][m]f[n−m][m]。
f[n][m]=f[n][m−1]+f[n−m][m]f[n][m]=f[n][m-1]+f[n-m][m] f[n][m]=f[n][m−1]+f[n−m][m]

2.将 nnn 个数划分成多个不大于 mmm 的数,不能存在相同整数

这个问题和上一个问题唯一的区别就在于不能存在相同整数,因此只需要修改第二种情况即可实现正确的转移。
f[n][m]=f[n][m−1]+f[n−m][m−1]f[n][m]=f[n][m-1]+f[n-m][m-1] f[n][m]=f[n][m−1]+f[n−m][m−1]

3.将 nnn 个数划分成 kkk 个数的划分方案

考虑 kkk 个数中是否存在 111。第一种情况从 nnn 个数中取出 kkk 个,保证剩下 kkk 组中每组数大于等于 222。第二种情况则保证 kkk 份中有至少一个 111,即先取出一个 111 分成 k−1k-1k−1 组。
f[n][k]=f[n−k][k]+f[n−1][k−1]f[n][k]=f[n-k][k]+f[n-1][k-1] f[n][k]=f[n−k][k]+f[n−1][k−1]

4.将 nnn 个数划分成不超过 kkk 个数的划分方案

此处枚举的是划分方案中是否有 kkk 组,f[n][k]f[n][k]f[n][k] 分别由划分组数小于 kkk 和划分组数等于 kkk 两种情况转移而来。
f[n][k]=f[n−k][k]+f[n][k−1]f[n][k]=f[n-k][k]+f[n][k-1] f[n][k]=f[n−k][k]+f[n][k−1]

5.将 nnn 个数划分若干奇数/偶数的划分方案

g[n][m]g[n][m]g[n][m]:将 nnn 划分为 mmm 个偶数的方案
f[n][m]f[n][m]f[n][m]:将 nnn 划分为 mmm 个奇数的方案

求 g[n][m]g[n][m]g[n][m] 只需从 nnn 中取出 mmm 个,然后将 f[n−m][m]f[n-m][m]f[n−m][m] 中的每个数+1+1+1,从奇数变成偶数即可。 求 f[n][m]f[n][m]f[n][m] 则需要考虑划分方案中有无 111 的情况,因为直接从 g[n−m][m]g[n-m][m]g[n−m][m] 转移过来,会丢失有 111 的这种情况。
g[n][m]=f[n−m][m]f[n][m]=f[n−1][m−1]+g[n−m][m]g[n][m]=f[n-m][m] \\ \ \\ f[n][m]=f[n-1][m-1]+g[n-m][m] g[n][m]=f[n−m][m] f[n][m]=f[n−1][m−1]+g[n−m][m]

6.将 nnn 个数划分成若干个数,使这若干个数的乘积最大

(1)(1)(1) 对于任意大于等于 444 的正整数 mmm,可以划分成 m=m1+m2m=m_1+m_2m=m1​+m2​,使得 m1∗m2≥mm_1*m_2\geq mm1​∗m2​≥m。

  • 证明:令 m1=(int)m/2,m2=m−m1m_1=(int)m/2,m_2=m-m_1m1​=(int)m/2,m2​=m−m1​,m1≥2,m2≥m1m_1\geq 2,m_2\geq m_1m1​≥2,m2​≥m1​ 且 m2>2m_2> 2m2​>2,则 m1∗m2≥2∗m2≥mm_1*m_2\geq 2*m_2\geq mm1​∗m2​≥2∗m2​≥m。

(2)(2)(2) 因此不断这样拆分下去,最后剩下的数一定是很多个 222 和 333 的组合,即 ans=2r∗3sans = 2^r*3^sans=2r∗3s,且 r≤2r\leq 2r≤2。

  • 若 r>2r>2r>2,则至少有 333 个因子为 222,而 2∗2∗2<3∗32*2*2<3*32∗2∗2<3∗3,且 2+2+2=3+32+2+2=3+32+2+2=3+3,因此 r≤2r\leq 2r≤2。

(3)(3)(3) 至此为止,不难发现答案只需对小于 444 的数分类讨论,对于大于 444 的数,枚举 222 的最少个数即可。

  • n=3∗rn=3*rn=3∗r,ans=3rans = 3^rans=3r
  • n=3∗r+1n=3*r+1n=3∗r+1,ans=3r−1∗2∗2ans=3^{r-1}*2*2ans=3r−1∗2∗2
  • n=3∗r+2n=3*r+2n=3∗r+2,ans=3r∗2ans=3^r*2ans=3r∗2

7.将 nnn 个数划分成若干个不同的数,使这若干个数的乘积最大

  • 拆分成的数的个数越多,乘积越大。因此找到第一个大于等于 nnn 的 Sx=∑i=2xiS_x = \sum\limits_{i=2}^{x}iSx​=i=2∑x​i。
  • 若 Sx=nS_x=nSx​=n,则 SxS_xSx​ 即为划分答案。
  • 若 Sx=n+1S_x = n+1Sx​=n+1,则将 SxS_xSx​ 中的 222 去掉,令 xxx 变成 x+1x+1x+1,即为最大值。
  • 若 Sx>n+1,k=Sx−nS_x>n+1,k=S_x-nSx​>n+1,k=Sx​−n,则答案为将 SxS_xSx​ 序列中的 kkk 去掉,剩下数构成最终答案。

参考博客


划分数习题

1. Drama

题意: 给出一个 H\text{H}H 行 N\text{N}N 列的网格,(r,c)(r,c)(r,c) 指第 rrr 行第 ccc 列的格子。现在需要在网格中选择 N\text{N}N 个格子涂成黑色。这 N\text{N}N 个格子需要满足一定的条件。

稍加模拟就会发现满足如上条件的格子组成了一个金字塔形状。如下图所示。

先要求给出一个 H\text{H}H 和 N\text{N}N,求出有多少种不同的涂法满足条件,答案模 109+710^9+7109+7。(1≤H,N≤105)(1\leq \text{H},\text{N}\leq 10^5)(1≤H,N≤105)

思路: 首先不难发现,若想满足题意进行格子涂色,则每行涂色的格子数必定逐行递减,因此可以发现涂色格子的行数一定在 N\sqrt \text{N}N​ 级别,即最多不会超过 400400400。

然后观察这个问题,这是个计数问题,比较常见的考虑就是使用 dpdpdp 进行转移计算答案。而使用 dpdpdp 的话,我们的选择就无非是按行从上往下 dpdpdp 转移,或者按列从左往右 dpdpdp 转移。(不过比赛的时候绝大多数想到的都只有按行从上往下)

如果按行从上往下转移,那怎么想都需要一个三维 dpdpdp,dp[i][j][k]dp[i][j][k]dp[i][j][k],第 iii 行,有 jjj 个格子,还剩 kkk 个格子没有填的方案数,然后就可以全队自闭了。思路陷在这里如果出不来就基本是告别 ACACAC 了。

既然行不可行,我们来考虑列转移,从左往右进行列的 dpdpdp 转移。我们从最高点将左右两边的金字塔划开,发现左边的金字塔列是不断递增上来的,即前一个与后一个要么高度不变,要么高度 +1+1+1。而右边的金字塔则只是递增,并没有严格的 +1+1+1 关系。

因此我们考虑对于左右两边进行分开 dpdpdp。左边状态为 f[i][j]f[i][j]f[i][j],表示 iii 个数,最大的数为 jjj 的方案个数,并且在转移过程严格要求一个数列非递减关系。而定义右边状态为 s[i][j]s[i][j]s[i][j],表示 iii 个数,所有的数小于等于 jjj 的方案个数。然后来分别思考转移方程。

左半部分转移方程,由于必须满足划分的数为非递减关系,因此我们枚举前一个数为 jjj 或 j−1j-1j−1,因此得到如下转移方程。
f[0][0]=1f[i][j]=f[i−j][j]+f[i−j][j−1]f[0][0] = 1 \\ \ \\ f[i][j]=f[i-j][j]+f[i-j][j-1] f[0][0]=1 f[i][j]=f[i−j][j]+f[i−j][j−1]

右半部分转移方程,只需满足所有数小于等于 jjj,因此可以类比之前的经典模型,iii 个数进行划分,最大的数不超过 jjj 的划分方案数。
s[0][i]=1s[i][j]=s[i][j−1]+s[i−j][j]s[0][i] = 1\\ \ \\ s[i][j] = s[i][j-1]+s[i-j][j] s[0][i]=1 s[i][j]=s[i][j−1]+s[i−j][j]

最后,枚举高度,然后再枚举左半部分格子数统计答案即可。

代码:

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i = a; i <= b; i++)
const int N = 1e5+100;
const int mod = 1e9+7;
using namespace std;int n,h,f[N][460],s[N][460];void init(){//f[i][j]: i个数, 最大的数为j, 方案个数f[0][0] = 1;rep(i,1,100000)rep(j,1,min(i,455)){f[i][j] = (f[i-j][j]+f[i-j][j-1])%mod;}//s[i][j]: i个数, 所有的数小于等于j, 方案个数rep(i,0,455) s[0][i] = 1;rep(i,1,100000){rep(j,1,455){s[i][j] = s[i][j-1];if(i >= j) s[i][j] = (s[i][j]+s[i-j][j])%mod;}}
}int main()
{init(); scanf("%d%d",&h,&n);long long ans = 0;//一开始先枚举高度, 整个题的思路也是这样, 但是根据内存连续性的问题, 必T无疑...我也成功找了一个小时bug才找到...//今后枚举数组时, 务必记得先枚举行, 再枚举列, 谨记今日教训rep(i,1,n)rep(j,1,min(h,455))ans = (ans+1ll*f[i][j]*s[n-i][j-1])%mod;printf("%lld\n",ans);return 0;
}

划分数算法概述及习题相关推荐

  1. 软件工程 科学出版社 郑逢斌主编 第1章 软件工程概述 课后习题答案

    软件工程 科学出版社 郑逢斌 第1章 软件工程概述 课后习题答案 1. 简述软件的发展过程. 2. 简述软件的定义和特点. 定义: 在 IEEE 软件工程词汇标准中,软件的定义是:软件是计算机程序.规 ...

  2. 目标反射回波检测算法及其FPGA实现 之一:算法概述

    目标反射回波检测算法及其FPGA实现之一:算法概述 前段时间,接触了一个声呐目标反射回波检测的项目.声呐接收机要实现的核心功能是在含有大量噪声的反射回波中,识别出发射机发出的激励信号的回波.我会分几篇 ...

  3. 算法设计与分析第1章 算法概述

    第1章 算法概述(穷举算法) 重要人物:Alan Turing(图灵机).Donald Knuth(TEX系统) 算法:解决问题的一种方法或一个过程 特性:有穷性(Finiteness).确定性(De ...

  4. 推荐系统产品与算法概述 | 深度

    作者丨gongyouliu 转载自大数据与人工智能(ID:gh_b8b5b02c348b) 作者在<推荐系统的工程实现>(点击蓝字可回顾)这篇文章的第五部分"推荐系统范式&quo ...

  5. 史上最全异常检测算法概述

    史上最全异常检测算法概述 参考文章: (1)史上最全异常检测算法概述 (2)https://www.cnblogs.com/Bang-cansee/p/4954129.html 备忘一下.

  6. Data Structures with C++ Using STL Chapter 3算法概述---笔记

    <Data Structures with C++ Using STL Chapter 3算法概述---笔记>,作者:茉莉花茶,原文链接:http://www.cnblogs.com/yc ...

  7. caliop 数据可视化_星载激光雷达CALIOP数据处理算法概述

    收稿日期 : 2017-08-05 : 修订日期 : 2017-11-27 基金项目 : (2016YFC0200700 , 2016YFC1400902 , 2016YFC400905) : (41 ...

  8. 动作分析 姿态估计_单人或多人的人体姿态骨架估计算法概述

    原标题:单人或多人的人体姿态骨架估计算法概述 如何在大片中实现人物的特效,最终应用人体姿态估计.本博客介绍了使用深度学习技术及其应用的多人姿势估计方法. 人体骨骼骨架以图形格式表达人体运动.基本上,它 ...

  9. 赫夫曼树编码的算法及应用习题--数据结构

    赫夫曼树编码的算法及应用习题 1.构造赫夫曼树的方法 1.根据给定的n个权值{w1,w2,---wn},构成n棵二叉树的集合F={T1,T2...,Tn},其中每棵二叉树中只有一个带权为Wi的根结点, ...

  10. java算法概述,Java数据结构与算法基础(一)概述与线性结构

    Java数据结构与算法基础(二)递归算法 Java数据结构与算法基础(一)概述与线性结构 学习目的:为了能更顺畅的读很多底层API代码和拓宽解决问题的思路 一.数据结构概述 1.数据结构是什么?数据与 ...

最新文章

  1. php-5.3.3安装注意问题
  2. 机器学习基础专题:高斯分布
  3. (一)java多线程之Thread
  4. ubuntu安装搜狗输入法的相关问题
  5. 在Linux下编译php扩展
  6. 13 个适合『中级开发者』练手的项目
  7. javaweb学习总结(二十五):jsp简单标签开发(一)
  8. linux 程序返回值 139,Linux系统监控之ssh登陆自动139邮件短信提醒
  9. ajax登录非空判断,email ajax传输数据去重和非空判断(示例代码)
  10. selenium-隐式等待和显式等待-0223
  11. cmdb整体项目梳理(2)
  12. 深度学习笔记(34) 目标检测
  13. Spring Cloud 负载均衡
  14. JVM判断对象是否存活
  15. 论我国证券市场的规范化管理
  16. 计算机论文图表,论文图表字体字号-毕业论文格式中图表的要求规范?
  17. android banner3d,XBanner实现3D画廊效果
  18. 计算机硬盘容量越大运行速度越快,你是不是也感觉电脑内存越大运行速度越快?...
  19. 618电商大数据分析可视化报告
  20. 改进型脉振高频注入源码 stm32工程 脉振高频注入是一种通过在d轴注入正弦电压

热门文章

  1. Reflector7.5.2.1的Bug
  2. ros 三线负载均衡
  3. python3调用js_关于python3运行JS文件的问题
  4. java json web token_一分钟简单了解JSON Web Token
  5. mysql sql语句执行到一半会怎么样?
  6. error: 'EOF' was not declared in this scope的解决办法
  7. linux系统expdp按表空间导出,expdp导出是全库吗
  8. php 的sentmail支持ssl吗_php 的swoole 和websocket 连接wss
  9. php本地文件包含 截断,php本地文件包含远程文件包含
  10. 【2019徐州网络赛:G】Colorful String(回文树+二进制统计回文串内不同字母数技巧)