HDOJ 1058 Humble Numbers解题报告【DP】

2023-05-16


 
 
Humble Numbers
题目详见http://acm.hdu.edu.cn/showproblem.php?pid=1058
	开始拿到这个题目的时候还纠结了半天,英语很差的话这个题是不可能AC的。。而我就是其中之一。。。
	Humber Number不用管它啥意思,就是一类定义的数而已。如果一个数的质因数(素因数)仅仅是2、3、5 or 7的话那就被称为Humber Number。特殊的1也在其列。而且题目给出了前20个Humber Number。1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25, 27。注意仅仅二字,11包含质因数11,26包含质因数13都不在其列。编写程序求第n个Humble Number。输入输出格式要搞明白。
	OK,搞清了题意,那就来分析一下。这个题的意思很清楚明了,就是给你一个N,求出第N个Humble Number。如何求?一开始我想到遍历,可是觉得很麻烦,估计会很超时。我就想啊,既然是2 3 5 7 ,我用1和他们相加如何?得到了3 4 6 8,这些数肯定是Humble Number。可是如何继续下去呢?用3和2 3 5 7相加?得到 5 6 8 10,还要用4和他们相加?继续下去?感觉很繁琐,就像是一颗树4叉树一样。  
	所以我放弃了这个思路,又开始想遍历,如果我知道了某个数是不是Humble Number,那我不就可以统计第N个了吗?从1开始遍历,如果i是Humble Number,那我就nums++,知道nums和你给定的N相等我们就求出了。。如何判断一个数是不是Humble Number呢?Humble Number的质因数只能是2 3 5 7 ,被这些数分别整除后结果肯定是1,而且整除次数最多是Number/2.
OK,上代码

#include <iostream>   
using namespace std;

//查看n是不是Humble Number
int IsHumbleNumber(long int n);
    
int main()
{	
	long int nums;
	long int number;
	long int i;
	while(cin>>number)
	{
		if(0==number)
			break;
		nums=0; //初始化  记录有多少个HumbleNumber 
		for(i=1;;i++)
		{
			if(IsHumbleNumber(i))
				nums++;
			if(number==nums)
				break;
		} //此时i的值就是第number个humble number
		//输出格式
		if((number>=4)&&(number<=20))
			cout<<"The "<<number<<"th humble number is "<<i<<endl; //英语差了这个题别想AC了。。。
		else if(1==(number-(number/10)*10))
			cout<<"The "<<number<<"st humble number is "<<i<<endl;
		else if(2==(number-(number/10)*10))
			cout<<"The "<<number<<"nd humble number is "<<i<<endl;
		else if(3==(number-(number/10)*10))
			cout<<"The "<<number<<"rd humble number is "<<i<<endl;
		else
			cout<<"The "<<number<<"th humble number is "<<i<<endl; 
	}
	return 0;
}


//查看n是不是Humble Number
int IsHumbleNumber(long int n)
{
	//long int num=1; 
	if(n==1)  //1 is Humble Number
		return true;
	long int num=n;
	long int i;
	for(i=1;i<=num/2;i++)
	{
		if(n%2==0)
			n/=2;
		else if(n%3==0)
			n/=3;
		else if(n%5==0)
			n/=5;
		else if(n%7==0)
			n/=7;
	}
	if(n==1)
		return true;
	else
		return false;
}


	提交之后发现超时,时间复杂度是Humber(N),这个N如果是5842,那么Humber(N)=20亿,超时是必然的结果。而且每次给定的N,都要从头来过。这让我想到了数组,用一个数组把所有的全部存起来,会不会好一些呢?
代码  
#include <iostream>   
using namespace std;

//查看n是不是Humble Number
int IsHumbleNumber(int n);
int main()
{	
	int nums;
	int number;
	long int i;
	int j;
	long int humble[5843]={0};//0位不用
	for(j=1;j<=5842;j++)
	{
		for(i=humble[j-1]+1;;i++)
		{
			if(IsHumbleNumber(i))
				break;
		} 
		humble[j]=i;//此时i的值就是第j个humble number
	}
	while(cin>>number)
	{
		if(0==number)
			break;

		//输出格式
		if((number>=4)&&(number<=20))
			cout<<"The "<<number<<"th humble number is "<<humble[number]<<endl; //英语差了这个题别想AC了。。。
		else if(1==(number-(number/10)*10))
			cout<<"The "<<number<<"st humble number is "<<humble[number]<<endl;
		else if(2==(number-(number/10)*10))
			cout<<"The "<<number<<"nd humble number is "<<humble[number]<<endl;
		else if(3==(number-(number/10)*10))
			cout<<"The "<<number<<"rd humble number is "<<humble[number]<<endl;
		else
			cout<<"The "<<number<<"th humble number is "<<humble[number]<<endl; 
	}
	return 0;
}


//查看n是不是Humble Number
int IsHumbleNumber(int n)
{
	//long int num=1; 
	if(n==1)  //1 is Humble Number
		return true;
	int num=n;
	int i;
	for(i=1;i<=num/2;i++)
	{
		if(n%2==0)
			n/=2;
		else if(n%3==0)
			n/=3;
		else if(n%5==0)
			n/=5;
		else if(n%7==0)
			n/=7;
	}
	if(n==1)
		return true;
	else
		return false;
}

	NO,还是超时!因为整个求Humber Number的过程是Humber(5842),也就是20亿,肯定会超时啦。。。所以来说,这个是行不通的。前100个还是很好求的,后面就不行了。
	逼不得已放弃这个思路。看这个20亿,我觉得时间复杂度可不可以是和N相关的和Humber Number没关系,O(N)?可以不?
	想一想开始时候的想法,4叉树,必然有很多相同的节点,那么这就是重叠子问题?而且求第N个Humber Number是和第N-1个Humber Number有关系的?也就是说问题的最优解可以用子问题的最优解来解决,这不是传说中的DP吗?
	OK,有点兴奋,怎么做?如何得到表达式?用第一次的思路,用加不行,可以用乘吗?1*2,1*3,1*5,1*7?得出的结果怎么办?所有的数还要和 2 3  5 7相乘,这不是和用加是一样的吗?绞尽脑汁,终于发现了一点规律了,一开始用1相乘的结果中最小值的就是2,这就是第2个Humber Number。然后呢?如果用2和2 3 5 7 相乘得到最小值是4,唉,不是3啊。可是如果2和2相乘 而3 5 7 还是和1相乘,那最小值不就是3了。YES!这是个规律。此时得到了2  3 ,如果用2和2相乘,3和2相乘,5 7 和1相乘,那么最小值就是4,OK,我发现新大陆了。	这个表达式好像就是用2 3 5 7和已经得到的Humber Number相乘啊。
	继续找规律,得到了4,那么如何得到5?3和2相乘,2和3相乘,1和5相乘,1和7相乘最小值就是5。和2 3 5 7 相乘的数就是之前的Humber Number,可是是哪个呢?根据刚才的规律我我们可以判断的是,一开始1,如果这个数和2 3 5 7 中的一个相乘得到的结果是最小值,那么就往后推一个Humber Number,也就是Humber数组的i++。如果有重复的都给他++。
	得到状态转移方程 humble[i]=FMin(humble[p2]*2,humble[p3]*3,humble[p5]*5,humble[p7]*7);
编码  

#include <iostream>   
using namespace std;

//求所有的Humble Number
void  HumbleNumber(long int humble[],int n);
long int FMin(long int m,long int n,long int k,long int l);    
int main()
{	
	int nums;
	int number;
	long int humble[5843];
	HumbleNumber(humble,5842);
	while(cin>>number)
	{
		if(0==number)
			break;

		//输出格式
		if((number>=4)&&(number<=20))
			cout<<"The "<<number<<"th humble number is "<<humble[number]<<"."<<endl; //英语差了这个题别想AC了。。。
		else if(1==(number-(number/10)*10))
			cout<<"The "<<number<<"st humble number is "<<humble[number]<<"."<<endl;
		else if(2==(number-(number/10)*10))
			cout<<"The "<<number<<"nd humble number is "<<humble[number]<<"."<<endl;
		else if(3==(number-(number/10)*10))
			cout<<"The "<<number<<"rd humble number is "<<humble[number]<<"."<<endl;
		else
			cout<<"The "<<number<<"th humble number is "<<humble[number]<<"."<<endl; 
	}
	return 0;
}


//求所有的Humble Number
void  HumbleNumber(long int humble[],int n)
{
	int i;
	int p2,p3,p5,p7;
	p2=p3=p5=p7=1;
	humble[1]=1;
	for(i=2;i<=n;i++)
	{
		humble[i]=FMin(humble[p2]*2,humble[p3]*3,humble[p5]*5,humble[p7]*7);
		if(humble[i]==humble[p2]*2)//不用else if 为了重复的
			p2++;
		if(humble[i]==humble[p3]*3)
			p3++;
		if(humble[i]==humble[p5]*5)
			p5++;
		if(humble[i]==humble[p7]*7)
			p7++;
	}
}

long int FMin(long int m,long int n,long int k,long int l)
{
	long int min1,min2;
	if(m<=n)
		min1=m;
	else
		min1=n;
	if(k<=l)
		min2=k;
	else
		min2=l;
	if(min1<=min2)
		return min1;
	else
		return min2;
}


	时间复杂度是O(N),就是在5842次就可以全部求出了,然后给定的N就可以O(1),得到结果了。很不错的算法。没有超时,nice!可是结果错误,我那个迷茫啊,彷徨啊。。可是仅仅发现输出结果少了一个尾号”.”,我赶紧添上,又是失败,看来不是这个问题,再说这也该是格式错误的提示啊。。
	最后我查了资料才发现,这个英语真心坑啊,看来不是4-20是th,判断的时候不仅仅是最后一位,还和最后两位有关系啊。。真心跪了。。
最后一次提交!!!  

#include <iostream>   
using namespace std;

//求所有的Humble Number
void  HumbleNumber(long int humble[],int n);
long int FMin(long int m,long int n,long int k,long int l);    
int main()
{	
	int nums;
	int number;
	long int humble[5843];
	HumbleNumber(humble,5842);
	while(cin>>number)
	{
		if(0==number)
			break;
		//输出格式
		if((1==number%10)&&(11!=number%100))
			cout<<"The "<<number<<"st humble number is "<<humble[number]<<"."<<endl;
		else if((2==number%10)&&(12!=number%100))
			cout<<"The "<<number<<"nd humble number is "<<humble[number]<<"."<<endl;
		else if((3==number%10)&&(13!=number%100))
			cout<<"The "<<number<<"rd humble number is "<<humble[number]<<"."<<endl;
		else
			cout<<"The "<<number<<"th humble number is "<<humble[number]<<"."<<endl; 
	}
	return 0;
}


//求所有的Humble Number
void  HumbleNumber(long int humble[],int n)
{
	int i;
	int p2,p3,p5,p7;
	p2=p3=p5=p7=1;
	humble[1]=1;
	for(i=2;i<=n;i++)
	{
		humble[i]=FMin(humble[p2]*2,humble[p3]*3,humble[p5]*5,humble[p7]*7);
		if(humble[i]==humble[p2]*2)//不用else if 为了重复的
			p2++;
		if(humble[i]==humble[p3]*3)
			p3++;
		if(humble[i]==humble[p5]*5)
			p5++;
		if(humble[i]==humble[p7]*7)
			p7++;
	}
}

long int FMin(long int m,long int n,long int k,long int l)
{
	long int min1,min2;
	if(m<=n)
		min1=m;
	else
		min1=n;
	if(k<=l)
		min2=k;
	else
		min2=l;
	if(min1<=min2)
		return min1;
	else
		return min2;
}



成功!!鲜红的Accepted,很有成就感啊。
总的来说这个题是不难的,只要用心去想肯定可以AC,这也算是很简单的DP啦。不得不吐槽的是和英语太有关系了。。。  
转载请注明出处http://blog.csdn.net/liangbopirates/article/details/9632829




本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HDOJ 1058 Humble Numbers解题报告【DP】 的相关文章

  • 如何将 ascii 值字符串转换为 python 中的原始字符/数字

    我有一个带有数字的字符串 我之前用编码器转换了它 但现在我正在尝试解码它 我四处搜索 似乎没有答案 如果你有任何办法 亲爱的 请告诉我 字符串 91 39 65 97 66 98 67 99 32 49 50 51 39 93 结果 ABC
  • python 中的阿姆斯特朗数

    num int input please enter number for num in range num 1000 sum1 0 numcp num if num gt 10 and num lt 100 while num gt 0
  • 如何从一组数字(不是范围)中生成随机数

    我希望能够从一组数字中生成一个随机数 例如 1 2 3 12 11 23 45 54 10 10 12 23 35 24 使用rand 和 srand 我可以每次生成不同的随机数 但我希望能够通过从一组生成随机数来调节结果 示例代码 取一个
  • Java:将(长)对象转换为双精度的多种方法

    我有一个Object obj我知道实际上是一个long 在一些数学代码中我需要它作为double 直接将其转换为双倍安全吗 double x double obj 或者我应该先将其转换为 long 然后再转换为 double double
  • 使用 JavaScript 计算 A、B、C、D,而不是 0、1、2、3...

    这可能是一个不寻常的请求 但对于我的脚本 我需要一个按字母而不是数字递增的函数 例如 这是一个数字示例 var i 0 while condition window write We are at i i 本质上 我想像 Microsoft
  • 求 500 的阶乘并将其存储在变量中...并执行计算...如何存储这么大的数字?

    我如何在变量 i 中存储大量数字并且不需要更改程序的大部分内容 例如 是否有可用的数据类型来存储 100 的阶乘 include
  • 从 NXC 中的文件返回负值

    我将值保存到 NXC 不是 eXactly C 中的 csv 文件 然后在稍后的时间点调用它们 我遇到的问题是 当从单元格中调用任何负值时 它会显示为 0123 而不是 123 这会导致我所有的额外计算失败 当前的代码是 OpenFileR
  • 检查字符串是否为实数[重复]

    这个问题在这里已经有答案了 有没有一种快速的方法来查找字符串是否是实数 而不是一次读取一个字符并执行isdigit 在每个角色上 例如 我希望能够测试浮点数0 03001 如果您将浮点数表示为实数 则这应该有效 def isfloat st
  • 在c中获取浮点数的指数

    抱歉 如果已经有人问过这个问题 并且我已经看到了提取浮点数指数的其他方法 但这就是给我的 unsigned f2i float f union unsigned i float f x x i 0 x f f return x i 我无法理
  • 科学记数法中的小“e”/Matlab中的Double是什么

    当我计算一个非常小的数字时 matlab给出 1 12345e 15这是什么 我可以将其解释为 1 12345 10 15 或其 1 12345 e 15 我很着急 抱歉问了这个愚蠢的问题 e 代表指数 它的科学计数法 http en wi
  • 在 Java 中用货币符号解析价格

    我想将我拥有的字符串解析为数字 这是我正在使用但不起作用的代码 NumberFormat getCurrencyInstance Locale GERMAN parse EUR 0 00 这会导致 java text ParseExcept
  • 将 pandas 中的数字格式化为以千或百万为单位的货币

    我有一个数据框 pd DataFrame Amount 19000000 9873200 823449242 我需要将数字转换为以百万计的货币 即 19 00MM 9 88MM 和 823 45MM 有谁知道一个快速的方法来做到这一点 Th
  • 使输入类型=“密码”在移动设备上使用数字键盘

    在我为移动设备设计的网站上 我有一个用于 PIN 码的输入字段 我希望在输入文本时隐藏文本 并且希望当移动设备上的用户想要输入 PIN 码时弹出数字键盘 当类型 数字 时 数字键盘会弹出 但当类型 密码 时 数字键盘不会弹出 并且我无法 或
  • 如何验证字符串是否是有效的浮点数? [复制]

    这个问题在这里已经有答案了 我想做的是验证字符串是否是数字 浮点数 但我还没有找到可以执行此操作的字符串属性 也许没有一个 我对这段代码有问题 N raw input Ingresa Nanometros if N and N isdigi
  • 大于100,000的随机数

    我正在用 C C 编写 我想创建很多大于 100 000 的随机数 我该怎么做呢 和rand 你不会那样做rand 但使用较新的 C 附带的适当随机数生成器 请参见例如cppreference com http en cppreferenc
  • 使用 QuasirandomGenerator (对于傻瓜来说)

    我是 CUDA 的新手 我正在努力在内核中生成随机数 我知道有不同的实现 而且 在 SDK 4 1 中有一个 Niederreiter 拟随机序列生成器的示例 我不知道从哪里开始 我有点悲伤 感觉自己像个傻瓜 有人可以制作一个使用 Nied
  • 创建后缀号码球拍

    我正在尝试在 Racket 中试验我可以做的事情 并且我想在数字后加上字母 对于这个例子 我只想代表10000 as 10K and 1000000 as 1M 有没有办法 用宏或其他方式 我可以扩展1M to 1 1000000 或者有什
  • C:如何将多位数分解为单独的变量?

    假设我在 C 中有一个多位整数 我想将它分解为一位数整数 123会变成1 2 and 3 我该如何做到这一点 特别是如果我不知道整数有多少位 int value 123 while value gt 0 int digit value 10
  • Android 数字格式不知为何是错误的,我得到的不是 3.5,而是 3.499999999,为什么?

    我将一些数据存储在数据库中 然后使用游标读取这些数据 所有数据均为 56 45 3 04 0 03 类型 即小数点后两位 现在我想对它们求和 但这似乎并不容易 我得到这些数字c getDouble 3 然后我将它添加到 sum 变量中 如下
  • 添加一个新列,其中标签附加到新月形数字

    我想添加一个新列 给出一个常量标签 并逐行附加新月数字逻辑 我的输入 position work chr1 jil2001 chr4 jil2001 chr3 kou2009 chr9 nai2012 chr7 fandis2005 我的预

随机推荐

  • MC9S12G128模块化分层化软件架构之七_外部中断

    文章目录 内容 1 overview 1 1 目的 2 优化内容 2 1 软件功能 2 2 编程健壮性 3 软件实现 3 1 Coding Rule 3 2 中断基础知识 3 2 1 mc9s12g128的中断向量号 3 2 2 mc9s1
  • 从期望到蒙特卡洛再到抽样(MCMC学习和梳理)

    文章目录 怎么计算期望用蒙特卡洛方法计算期望 xff08 积分 xff09 无法使用蒙特卡洛计算积分的情况 无法采样接受 拒绝采样重要性采样MCMCMetropolis Hasting算法实现 Reference 近期在学习MCMC Mar
  • python3中替换python2中cmp函数的新函数分析(lt、le、eq、ne、ge、gt)

    本文地址 xff1a http blog csdn net sushengmiyan article details 11332589 作者 xff1a sushengmiyan 在python2中我们经常会使用cmp函数来比较一些东西 x
  • Eclipse中查看没有源码的Class文件的方法

    本文地址 http blog csdn net sushengmiyan article details 18798473 本文作者 sushengmiyan 我们在使用Eclipse的时候 xff0c 经常是会使用别人的Jar包 xff0
  • [ExtJS5学习笔记]第二节 Sencha Cmd 学习笔记 使你的sencha cmd跑起来

    本文地址 xff1a http blog csdn net sushengmiyan article details 38313537 本文作者 xff1a sushengmiyan 资源链接 翻译来源 Sencha Cmd官方网站 xff
  • 【Java二十周年】Delphi转行java的一些小感触

    本文纯属一届小码农对java使用过程的体验感触 目录 xff1a 初遇java编程语言与java的擦肩深入java 跨平台性开源支持web的支撑 初遇java编程语言 刚上大学的时候 xff0c 完全是个电脑盲 刚入学学的计算机普及知识就是
  • Vmware-虚拟中的linux如何增加硬盘(转)

    启动虚拟机软件VMware后 xff0c 点机VM菜单选择Setting xff0c 然后在弹出地菜单中选择 xff1a Add命令进行添加硬盘操作 完成后启动虚拟机 1 建立分区 fdisk l查看磁盘分区情况 此时你会发现多了一个 de
  • 给大家安利一个学习angular2的视频网站

    本文地址 xff1a http blog csdn net sushengmiyan 本文作者 xff1a 苏生米沿 视频地址 xff1a https egghead io courses angular 2 fundamentals 网站
  • 记一个万金油开源框架JHipster

    本文地址 xff1a http blog csdn net sushengmiyan article details 53190236 百搭代码生成框架 体验新技术汇总 xff1a Spring BootSpring SecurityAng
  • SQLServer触发器创建、删除、修改、查看...适用于级联删除

    一 触发器是一种特殊的存储过程 它不能被显式地调用 而是在往表中插入记录 更新记录或者删除记录时被自动地激活 所以触发器可以用来实现对表实施复杂的完整性约束 二 SQL Server为每个触发器都创建了两个专用表 Inserted表和Del
  • 工薪族巧理财之定期存款中整存整取、零存整取、存本取息之间的微妙区别

    银行的官方术语先给大家普及一下 xff1a 定期存款是在存款时约定存储时间 一次或按期分次 在约定存期 存入本金 xff0c 整笔或分期平均支取本金利息的一种储蓄 按存取方式定期存款分为整存整取定期存款 零存整取定期存款 存本取息定期存款
  • no module named win32com.client错误解决

    无论什么时候 xff0c 你在运行的时候发现有importError no module named win32com client这个提示 你都可以这么解决 xff1a 请下载http sourceforge net projects p
  • java.util.concurrent同步框架(AQS论文中文翻译)

    java util concurrent同步框架 摘要目录和主题描述一般条款关键字1 介绍 xff1a 需求设计实现4 使用方式5 性能6 结论7 致谢 Doug Lea SUNY Oswego Oswego NY 13126 dl 64
  • POJ2287 田忌赛马---贪心算法

    田忌赛马 题目详见http poj org problem id 61 2287 田忌赛马大家都听过 xff0c 可是如果不是上中下三等马 xff0c 而是很多匹马 xff0c 优劣有很多种分类 xff0c 就不仅仅是321的问题了 这个很
  • 贪心算法详解

    之前讲过动态规划DP xff0c 现在来说说贪心 贪心算法在解决问题的策略上目光短浅 xff0c 只根据当前已有的信息就做出选择 xff0c 而且一旦做出了选择 xff0c 不管将来有什么结果 xff0c 这个选择都不会改变 也就是说贪心对
  • 搜索智能提示suggestion,附近点搜索

    第三十六 三十七章 搜索智能提示suggestion xff0c 附近地点搜索 作者 xff1a July 致谢 xff1a caopengcs 胡果果 时间 xff1a 二零一三年九月七日 题记 写博的近三年 xff0c 整理了太多太多的
  • 多重继承及虚继承中对象内存的分布

    多重继承及虚继承中对象内存的分布 这篇文章主要讲解G 43 43 编译器中虚继承的对象内存分布问题 xff0c 从中也引出了dynamic cast和static cast本质区别 虚函数表的格式等一些大部分C 43 43 程序员都似是而非
  • Linux日志服务器配置

    配置日志服务器 环境 xff1a tibet xff1a 10 11 3 57 gaplinux xff08 日志服务器 xff09 xff1a 10 11 3 3 修改tibet上的 etc hosts xff0c 增加如下代码 xff1
  • 【Google】25匹马的角逐

    问题是这样的 xff1a 一共有25匹马 xff0c 有一个赛场 xff0c 赛场有5个赛道 xff0c 就是说最多同时可以有5匹马一起比赛 假设每匹马都跑的很稳定 xff0c 不用任何其他工具 xff0c 只通过马与马之间的比赛 xff0
  • HDOJ 1058 Humble Numbers解题报告【DP】

    Humble Numbers 题目详见http acm hdu edu cn showproblem php pid 61 1058 开始拿到这个题目的时候还纠结了半天 xff0c 英语很差的话这个题是不可能AC的 而我就是其中之一 Hum