【动态规划】【 数位dp】2827. 范围中美丽整数的数目

这篇具有很好参考价值的文章主要介绍了【动态规划】【 数位dp】2827. 范围中美丽整数的数目。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文涉及知识点

数位dp
动态规划汇总

LeetCode2827. 范围中美丽整数的数目

给你正整数 low ,high 和 k 。
如果一个数满足以下两个条件,那么它是 美丽的 :
偶数数位的数目与奇数数位的数目相同。
这个整数可以被 k 整除。
请你返回范围 [low, high] 中美丽整数的数目。
示例 1:
输入:low = 10, high = 20, k = 3
输出:2
解释:给定范围中有 2 个美丽数字:[12,18]

  • 12 是美丽整数,因为它有 1 个奇数数位和 1 个偶数数位,而且可以被 k = 3 整除。
  • 18 是美丽整数,因为它有 1 个奇数数位和 1 个偶数数位,而且可以被 k = 3 整除。
    以下是一些不是美丽整数的例子:
  • 16 不是美丽整数,因为它不能被 k = 3 整除。
  • 15 不是美丽整数,因为它的奇数数位和偶数数位的数目不相等。
    给定范围内总共有 2 个美丽整数。
    示例 2:
    输入:low = 1, high = 10, k = 1
    输出:1
    解释:给定范围中有 1 个美丽数字:[10]
  • 10 是美丽整数,因为它有 1 个奇数数位和 1 个偶数数位,而且可以被 k = 1 整除。
    给定范围内总共有 1 个美丽整数。
    示例 3:
    输入:low = 5, high = 5, k = 2
    输出:0
    解释:给定范围中有 0 个美丽数字。
  • 5 不是美丽整数,因为它的奇数数位和偶数数位的数目不相等。
    提示:
    0 < low <= high <= 109
    0 < k <= 20

数位dp

直接使用封装类,枚举类型char,最小值’0’,最大值’9’,结果类型:int。
状态数量:400。
i1 = 奇数数数量-偶数位数量+10,取值范围 ∈ \in [1,19]
i2 = 当前数字%k
状态压缩:20*i1+i2

代码

核心代码


template<class ELE, class ResultType, ELE minEle, ELE maxEle>
class CLowUperr
{
public:

	CLowUperr(int iCustomStatusCount) :m_iCustomStatusCount(iCustomStatusCount)
	{
	}
	void Init(const ELE* pLower, const ELE* pHigh, int iNum)
	{
		m_vPre.assign(4, vector<ResultType>(m_iCustomStatusCount));
		if (iNum <= 0)
		{
			return;
		}
		InitPre(pLower, pHigh);
		iNum--;
		while (iNum--)
		{
			pLower++;
			pHigh++;
			vector<vector<ResultType>> dp(4, vector<ResultType>(m_iCustomStatusCount));
			OnInitDP(dp);
			//处理非边界
			for (auto tmp = minEle; tmp <= maxEle; tmp++)
			{
				OnEnumOtherBit(dp[0], m_vPre[0], tmp);
			}
			//处理下边界
			OnEnumOtherBit(dp[1], m_vPre[1], *pLower);
			for (auto tmp = *pLower + 1; tmp <= maxEle; tmp++)
			{
				OnEnumOtherBit(dp[0], m_vPre[1], tmp);
			}
			//处理上边界
			OnEnumOtherBit(dp[2], m_vPre[2], *pHigh);
			for (auto tmp = minEle; tmp < *pHigh; tmp++)
			{
				OnEnumOtherBit(dp[0], m_vPre[2], tmp);
			}
			//处理上下边界
			if (*pLower == *pHigh)
			{
				OnEnumOtherBit(dp[3], m_vPre[3], *pLower);
			}
			else
			{
				OnEnumOtherBit(dp[1], m_vPre[3], *pLower);
				for (auto tmp = *pLower + 1; tmp < *pHigh; tmp++)
				{
					OnEnumOtherBit(dp[0], m_vPre[3], tmp);
				}
				OnEnumOtherBit(dp[2], m_vPre[3], *pHigh);
			}
			m_vPre.swap(dp);
		}
	}
protected:
	const int m_iCustomStatusCount;
	void InitPre(const ELE* const pLower, const ELE* const pHigh)
	{
		for (ELE cur = *pLower; cur <= *pHigh; cur++)
		{
			int iStatus = 0;
			if (*pLower == cur)
			{
				iStatus = *pLower == *pHigh ? 3 : 1;
			}
			else if (*pHigh == cur)
			{
				iStatus = 2;
			}
			OnEnumFirstBit(m_vPre[iStatus], cur);
		}
	}

	virtual void OnEnumOtherBit(vector<ResultType>& dp, const vector<ResultType>& vPre, ELE curValue) = 0;

	virtual void OnEnumFirstBit(vector<ResultType>& vPre, const ELE curValue) = 0;
	virtual void OnInitDP(vector<vector<ResultType>>& dp)
	{

	}
	vector<vector<ResultType>> m_vPre;
};

class CMy : public CLowUperr<char, int, '0', '9'>
{
public:
	typedef  int ResultType;
	typedef  char ELE;
	CMy(int k) :CLowUperr<char, int, '0', '9'>(400), m_iK(k)
	{

	}
	virtual void OnEnumOtherBit(vector<ResultType>& dp, const vector<ResultType>& vPre, ELE curValue)
	{
		const int index = curValue - '0';
		for (int iPreMask = 0; iPreMask < m_iCustomStatusCount; iPreMask++)
		{
			const int preK = iPreMask % 20;
			const int pre01 = iPreMask / 20 ;
			const int k = (preK*10+index) % m_iK;
			int i01 = (index & 1) ? 1 : -1;
			if ((pre01 + i01 < 0) || (pre01 + i01 >= 20))
			{
				continue;
			}
			const int mask = Mask(pre01+i01-10, k);
			dp[mask] += vPre[iPreMask];
		}
	}

	virtual void OnEnumFirstBit(vector<ResultType>& vPre, const ELE curValue)
	{
		const int index = curValue - '0';
		const int k = index % m_iK;
		int i01 = (index & 1) ? 1 : -1;
		const int mask = Mask(i01,k);
		vPre[mask]++;
	}
	int Result()const
	{
		int iRet = 0;
		for (int status = 0; status < 4; status++)
		{
			iRet += m_vPre[status][200];
		}
		return iRet;
	}
protected:
	int Mask(int i01, int k) {	return (i01 + 10) * 20 + k;	}
	const int m_iK;
};
class Solution {
public:
	int numberOfBeautifulIntegers(int low, int high, int iK) {
		string strLow = std::to_string(low);
		string strHigh = std::to_string(high);
		int iRet = 0;
		const int len1 = strLow.length();
		const int len2 = strHigh.length();
		if (len1 == len2)
		{
			return Do(strLow, strHigh, iK);
		}
		iRet += Do(strLow, string(len1, '9'),iK);
		for (int i = len1 + 1; i < len2; i++)
		{
			iRet += Do("1" + string(i - 1, '0'), string(i, '9'), iK);
		}
		iRet += Do("1" + string(len2 - 1, '0'), strHigh, iK);
		return iRet;
	}
	int Do(const string strLow,const string& strHigh,int k)
	{
		CMy my(k);
		my.Init(strLow.data(), strHigh.data(), strLow.length());
		return my.Result();
	}
};

测试用例


template<class T, class T2>
void Assert(const T& t1, const T2& t2)
{
	assert(t1 == t2);
}

template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
	if (v1.size() != v2.size())
	{
		assert(false);
		return;
	}
	for (int i = 0; i < v1.size(); i++)
	{
		Assert(v1[i], v2[i]);
	}

}

int main()
{
	
	int low = 1, high = 10, k = 1;
	{
		low = 1, high = 10, k = 1;
		auto res = Solution().numberOfBeautifulIntegers(low, high, k);
		Assert(1, res);
	}
	{
		low = 5, high = 5, k = 2;
		auto res = Solution().numberOfBeautifulIntegers(low, high, k);
		Assert(0, res);
	}
	{
		low = 10, high = 20, k = 3;
		auto res = Solution().numberOfBeautifulIntegers(low, high, k);
		Assert(2, res);
	}
	
}

【动态规划】【 数位dp】2827. 范围中美丽整数的数目,# 算法题,动态规划,算法,c++,美丽数字,范围,数位dp,整除

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关

下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

【动态规划】【 数位dp】2827. 范围中美丽整数的数目,# 算法题,动态规划,算法,c++,美丽数字,范围,数位dp,整除文章来源地址https://www.toymoban.com/news/detail-848273.html

到了这里,关于【动态规划】【 数位dp】2827. 范围中美丽整数的数目的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++ 动态规划 数位统计DP 计数问题

    给定两个整数 a 和 b ,求 a 和 b 之间的所有数字中 0∼9 的出现次数。 例如,a=1024,b=1032 ,则 a 和 b 之间共有 9 个数如下: 1024 1025 1026 1027 1028 1029 1030 1031 1032 其中 0 出现 10 次,1 出现 10 次,2 出现 7 次,3 出现 3 次等等… 输入格式 输入包含多组测试数据。 每组测试数据占一

    2024年02月20日
    浏览(30)
  • 【数位dp】【动态规划】C++算法:233.数字 1 的个数

    视频算法专题 动态规划汇总 给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。 示例 1: 输入:n = 13 输出:6 示例 2: 输入:n = 0 输出:0 提示: 0 = n = 10 9 本题比较简单,主要讲封装类。m_vPre记录上一位所有状态,程序结束时,记录的是最后一位的所有

    2024年01月16日
    浏览(30)
  • acwing算法基础之动态规划--数位统计DP、状态压缩DP、树形DP和记忆化搜索

    暂无。。。 暂无。。。 题目1 :求a~b中数字0、数字1、…、数字9出现的次数。 思路:先计算1~a中每位数字出现的次数,然后计算1~b-1中每位数字出现的次数,两个相减即是最终答案。 那么,如何计算1~a中每位数字出现的次数呢? 首先,将a的每一位存入向量num中,例如a=123

    2024年02月04日
    浏览(38)
  • 动态规划——数位

    ”某一区间“满足某种性质 技巧1:[x,y]=f[y]-f[x-1]; 技巧2:树; 模板如下: 例1:度的数量 分析: 例2、数字游戏 分析: 例3、 Windy数 如果要求dp(1567),由于第一个根节点的分叉左枝干是从1开始,那么就等于0-999都没有算进res里面 好好理解f的含义,例如f[3] [9]表示最高位为

    2024年02月04日
    浏览(24)
  • Leetcode 第 108 场双周赛 Problem C 将字符串分割为最少的美丽子字符串(动态规划)

    Leetcode 第 108 场双周赛 Problem C 将字符串分割为最少的美丽子字符串(动态规划) 题目 给你一个二进制字符串 s ,你需要将字符串分割成一个或者多个 子字符串 ,使每个子字符串都是 美丽 的。 如果一个字符串满足以下条件,我们称它是 美丽 的: 它不包含前导 0 。 它是

    2024年02月15日
    浏览(33)
  • 动态规划(DP)入门——线性DP

    在了解线性DP之前,我们首先要知道什么是动态规划,即为将一种复杂问题,分解成很多重叠的子问题,并通过子问题的解得到整个问题的解的算法。听起来比较抽象,动态规划简单来说就是确定问题的状态,通常题目都会提示,一般为“到第i个为止,xx为j(xx为k)的方案数/最

    2024年02月19日
    浏览(31)
  • 【动态规划】【子序列除重】【C++算法】1987不同的好子序列数目

    【动态规划】【状态压缩】【2次选择】【广度搜索】1494. 并行课程 II 动态规划汇总 给你一个二进制字符串 binary 。 binary 的一个 子序列 如果是 非空 的且没有 前导 0 (除非数字是 “0” 本身),那么它就是一个 好 的子序列。 请你找到 binary 不同好子序列 的数目。 比方说,

    2024年02月21日
    浏览(29)
  • 动态规划报告(树形DP+概率DP

    树形 DP,即在树上进行的 DP。由于树固有的递归性质,树形 DP 一般都是递归进行的。一般需要在遍历树的同时维护所需的信息 以一道题目为例 2022CCPC桂林站G Group Homework No, we don’t want group homework. It’s the place where 1+11 can be true. However, you are currently the leader of a group with three

    2024年02月12日
    浏览(38)
  • 美丽序列(Dp)

    传送门 牛牛喜欢整数序列,他认为一个序列美丽的定义是 1:每个数都在0到40之间 2:每个数都小于等于之前的数的平均值 具体地说:for each i, 1 = i N,  A[i] = (A[0] + A[1] + ... + A[i-1]) / i. 3:没有三个连续的递减的数 现在给你一个序列,每个元素是-1到40,你可以将序列中的-1修改

    2024年02月13日
    浏览(23)
  • DP算法:动态规划算法

    (1)确定初始状态 (2)确定转移矩阵,得到每个阶段的状态,由上一阶段推到出来 (3)确定边界条件。 蓝桥杯——印章(python实现) 使用dp记录状态,dp[i][j]表示买i张印章,凑齐j种印章的概率 i表示买的印章数,j表示凑齐的印章种数 情况一:如果ij,不可能凑齐印章,概

    2024年02月07日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包