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】 的相关文章

  • Rails 中数字的本地化

    对新帖子感到抱歉 但我的第一个帖子关注的是阿拉伯 波斯数字 但问题似乎更大 我想知道是否有人做了一个 gem 来处理 ruby rails 中数字的本地化 I18n 官方语言环境 https github com svenfuchs rai
  • 生成偶数随机数

    我需要一个代码来仅生成随机偶数 2 100网上有生成随机数的教程 但它们有奇数和偶数 请理解我只需要生成偶数 1 生成数字1 50 2 将所有数字乘以2 所有数字乘以 2 都是偶数
  • 改进的 isNumeric() 函数?

    在一些项目中 我需要验证一些数据 并尽可能确定它是可用于数学运算的 JavaScript 数值 jQuery 和其他一些 javascript 库已经包含这样的函数 通常称为 isNumeric 还有一个发布在 stackoverflow
  • 科学记数法中的小“e”/Matlab中的Double是什么

    当我计算一个非常小的数字时 matlab给出 1 12345e 15这是什么 我可以将其解释为 1 12345 10 15 或其 1 12345 e 15 我很着急 抱歉问了这个愚蠢的问题 e 代表指数 它的科学计数法 http en wi
  • 从数组中打印素数

    我想用方法从数组中打印出所有素数 我可以用一个 int 来完成 但不知道如何从数组中返回某些数字 感谢帮助 public static boolean isPrime int tab boolean prime true for int i
  • 仅使用 Y 数即可得出小于 X 的所有可能性?

    假设我有这些数字 2 25 37 54 54 76 88 91 99 这些是随机的 我需要找到小于 100 的数字的所有组合 并非所有数字都必须在这些组合中使用 示例 2 2 25 37 54 25 我怎样才能在 JavaScript 中实
  • 如何将数字(如 int)转换为“Number”?

    这可能是基本问题 但我找不到有用的东西 问题是 如何转换double or int价值Number类型 更具体地说oracle jbo domain Number 我尝试了以下方法 对于整数值 int i 9 Integer y new I
  • 将 css 宽度字符串转换为常规数字

    在尝试计算隐藏元素的宽度时 我发现 jquery width 对于该元素的宽度返回 0 我发现使用 jquery css width 将通过使用声明的样式宽度返回正确的宽度 即使该值与初始样式表不同 问题是 css width 方法返回一个
  • 使用 rmultinom() 函数从 R 中的多项分布生成随机数

    我想从具有三个值的多项分布生成大小为 20 的样本 例如1 2 and 3 例如 样本可以是这样的sam 1 2 2 2 2 3 1 1 1 3 3 3 2 1 2 3 1 下面的代码可以工作 但没有得到预期的结果 gt rmultinom
  • Android 软键盘先显示数字视图

    我的应用程序上有一个登录屏幕 它接受 CPF 作为登录名 CPF 是每个巴西公民都有的唯一号码标识 例如 10546819546 但它也可以接受护照号码作为登录名 并且上面可能有字母 我的问题是我希望键盘在弹出时在默认字母表之前显示数字 符
  • 在java中以一定精度显示双精度数

    我目前正在编写一个计算器应用程序 我知道双精度数并不是良好数学的最佳选择 应用程序中的大多数函数都具有很高的精度 但有些函数不会得到非常难看的结果 我的解决方案是只向用户显示 12 位小数的精度 我选择 12 是因为我的最低精度来自我的数值
  • 具有非常大的数字的除法

    我只是想知道在处理大数字时有哪些不同的除法策略 我所说的大数字是指 50 位数字 例如 9237639100273856744937827364095876289200667937278 82637448262718273966299344
  • 在 php 中将单词转换为数字 II

    这里有一个很棒的功能在 PHP 中将单词转换为数字 https stackoverflow com questions 1077600 converting words to numbers in php来自埃尔约博 但我有一个问题 字符串
  • 正则表达式允许零,只要它不是第一个数字[重复]

    这个问题在这里已经有答案了 昨天我在这里发布了一个问题正则表达式允许 null 或 1 到 9 数字 https stackoverflow com questions 40354842 regular expression allow n
  • Javascript:生成具有固定平均值和标准差的随机数

    我的问题 如何在 Javascript 中创建具有给定平均值和标准差 sd 的随机数列表 Example 我想创建一个包含 5 个范围在 1 到 10 之间的随机数的列表 生成的平均值应为 5 标准差应为 2 到目前为止我所做的 我的想法是
  • Python,质数检查器[重复]

    这个问题在这里已经有答案了 你好 我正在创建一个函数来检查一个数字是否是素数 但它告诉我 9 是一个素数 def eprimo num if num lt 2 return False if num 2 return True else f
  • 如何对“2-1”这样的字符串进行数学计算以产生“1”?

    我只是想知道 PHP 是否有一个函数可以接受像这样的字符串2 1并产生它的算术结果 或者我必须手动执行此操作explode 获取算术运算符左侧和右侧的值 我知道这个问题很老了 但我昨晚在寻找不太相关的东西时遇到了它 而且这里的每个答案都很糟
  • php同时上传最大文件数

    我正在使用标签 用于使用 php 上传多个文件 我注意到 如果我选择超过 20 个文件 php 只会上传前 20 个文件 有没有办法扩大这个限制 这个限制被添加到PHP 5 2 12 https www php net releases 5
  • 如何在fortran 90中生成[0,5]范围内的整数随机数?

    我对 Fortran 编程有点陌生 任何人都可以帮我解决问题吗 我在生成整数随机数时遇到问题 在 Fortran 随机数范围 0 5 中使用 random seed 和 rand 为了支持answer https stackoverflow
  • 有没有对数字(千)进行分组的函数?

    小 模块中是否隐藏着一个函数 它为我执行此操作 my var 23654325432 var reverse var var s d 3 K d g var reverse var I like 数字 格式 http search cpan

随机推荐

  • Docker常用命令,脚本在线或者离线安装Docker

    目录 常用命令停止容器 Docker镜像打包到另一台服务器 xff08 压缩包 xff09 Docker镜像打包到另一台服务器 xff08 使用Docker Hub xff09 Docker在线和离线安装卸载Docker 常用命令 span
  • docker镜像使用基础命令

    列出镜像列表 docker images REPOSITORY xff1a 表示镜像的仓库源 TAG xff1a 镜像的标签 用冒号分隔 版本标签 如果不指定就默认为latest IMAGE ID xff1a 镜像ID CREATED xf
  • 如何快速搜索文件和文件内容

    苏生不惑第144 篇原创文章 xff0c 将本公众号设为星标 xff0c 第一时间看最新文章 平常搜索文件一般会直接这样搜 xff0c 不过如果文件太多的话会很慢 xff0c 而且没法搜索文件内容 这里分享几个好用的文件搜索工具 Every
  • 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 完全是个电脑盲 刚入学学的计算机普及知识就是
  • 给大家安利一个学习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 整笔或分期平均支取本金利息的一种储蓄 按存取方式定期存款分为整存整取定期存款 零存整取定期存款 存本取息定期存款
  • CentOS防火墙相关命令

    目录 1 开放端口2 查看防火墙所有开放的端口3 关闭防火墙4 查看防火墙状态5 查看监听的端口6 检查端口被哪个进程占用7 查看进程的详细信息 1 开放端口 firewall cmd zone span class token opera
  • 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 程序员都似是而非
  • 【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