划分数算法概述及习题
前言
如果你对这篇文章可感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。
划分数概述
一、适用问题
只要涉及一些难以用组合公式直接求得的数的划分问题。比如将 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∑xi。
- 若 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
- (1,1)(1,1)(1,1) 需要涂黑。
- 如果 (r,a)(r,a)(r,a) 与 (r,b)(r,b)(r,b) 涂黑了,则 (r,k)(r,k)(r,k) 为黑。a<k<ba<k<ba<k<b,即每行涂黑的格子必须是连续的。
- 如果 (r,c)(r,c)(r,c) 涂黑了,则 (r−1,c)(r-1,c)(r−1,c) 如果存在,也必须涂黑。
- 如果 (r,c)(r,c)(r,c) 涂黑了,并且现在没有任何 k<ck<ck<c 使得 (r,k)(r,k)(r,k) 是黑的,则 (r+1,c)(r+1,c)(r+1,c) 为白。
思路:
首先不难发现,若想满足题意进行格子涂色,则每行涂色的格子数必定逐行递减,因此可以发现涂色格子的行数一定在 N\sqrt \text{N}N 级别,即最多不会超过 400400400。
#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. 简述软件的发展过程. 2. 简述软件的定义和特点. 定义: 在 IEEE 软件工程词汇标准中,软件的定义是:软件是计算机程序.规 ...
- 目标反射回波检测算法及其FPGA实现 之一:算法概述
目标反射回波检测算法及其FPGA实现之一:算法概述 前段时间,接触了一个声呐目标反射回波检测的项目.声呐接收机要实现的核心功能是在含有大量噪声的反射回波中,识别出发射机发出的激励信号的回波.我会分几篇 ...
- 算法设计与分析第1章 算法概述
第1章 算法概述(穷举算法) 重要人物:Alan Turing(图灵机).Donald Knuth(TEX系统) 算法:解决问题的一种方法或一个过程 特性:有穷性(Finiteness).确定性(De ...
- 推荐系统产品与算法概述 | 深度
作者丨gongyouliu 转载自大数据与人工智能(ID:gh_b8b5b02c348b) 作者在<推荐系统的工程实现>(点击蓝字可回顾)这篇文章的第五部分"推荐系统范式&quo ...
- 史上最全异常检测算法概述
史上最全异常检测算法概述 参考文章: (1)史上最全异常检测算法概述 (2)https://www.cnblogs.com/Bang-cansee/p/4954129.html 备忘一下.
- Data Structures with C++ Using STL Chapter 3算法概述---笔记
<Data Structures with C++ Using STL Chapter 3算法概述---笔记>,作者:茉莉花茶,原文链接:http://www.cnblogs.com/yc ...
- caliop 数据可视化_星载激光雷达CALIOP数据处理算法概述
收稿日期 : 2017-08-05 : 修订日期 : 2017-11-27 基金项目 : (2016YFC0200700 , 2016YFC1400902 , 2016YFC400905) : (41 ...
- 动作分析 姿态估计_单人或多人的人体姿态骨架估计算法概述
原标题:单人或多人的人体姿态骨架估计算法概述 如何在大片中实现人物的特效,最终应用人体姿态估计.本博客介绍了使用深度学习技术及其应用的多人姿势估计方法. 人体骨骼骨架以图形格式表达人体运动.基本上,它 ...
- 赫夫曼树编码的算法及应用习题--数据结构
赫夫曼树编码的算法及应用习题 1.构造赫夫曼树的方法 1.根据给定的n个权值{w1,w2,---wn},构成n棵二叉树的集合F={T1,T2...,Tn},其中每棵二叉树中只有一个带权为Wi的根结点, ...
- java算法概述,Java数据结构与算法基础(一)概述与线性结构
Java数据结构与算法基础(二)递归算法 Java数据结构与算法基础(一)概述与线性结构 学习目的:为了能更顺畅的读很多底层API代码和拓宽解决问题的思路 一.数据结构概述 1.数据结构是什么?数据与 ...
最新文章
- php-5.3.3安装注意问题
- 机器学习基础专题:高斯分布
- (一)java多线程之Thread
- ubuntu安装搜狗输入法的相关问题
- 在Linux下编译php扩展
- 13 个适合『中级开发者』练手的项目
- javaweb学习总结(二十五):jsp简单标签开发(一)
- linux 程序返回值 139,Linux系统监控之ssh登陆自动139邮件短信提醒
- ajax登录非空判断,email ajax传输数据去重和非空判断(示例代码)
- selenium-隐式等待和显式等待-0223
- cmdb整体项目梳理(2)
- 深度学习笔记(34) 目标检测
- Spring Cloud 负载均衡
- JVM判断对象是否存活
- 论我国证券市场的规范化管理
- 计算机论文图表,论文图表字体字号-毕业论文格式中图表的要求规范?
- android banner3d,XBanner实现3D画廊效果
- 计算机硬盘容量越大运行速度越快,你是不是也感觉电脑内存越大运行速度越快?...
- 618电商大数据分析可视化报告
- 改进型脉振高频注入源码 stm32工程 脉振高频注入是一种通过在d轴注入正弦电压
热门文章
- Reflector7.5.2.1的Bug
- ros 三线负载均衡
- python3调用js_关于python3运行JS文件的问题
- java json web token_一分钟简单了解JSON Web Token
- mysql sql语句执行到一半会怎么样?
- error: 'EOF' was not declared in this scope的解决办法
- linux系统expdp按表空间导出,expdp导出是全库吗
- php 的sentmail支持ssl吗_php 的swoole 和websocket 连接wss
- php本地文件包含 截断,php本地文件包含远程文件包含
- 【2019徐州网络赛:G】Colorful String(回文树+二进制统计回文串内不同字母数技巧)