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

  • 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
  • 需要解释“~0”与“2**64”(带和不带“使用整数”)

    我编写了一些测试程序打印的值 0 and 2 64 usr bin perl use warnings use strict use integer print 0 n print 2 64 n Without use integer程序输
  • JavaScript 数字到单词

    例如 我正在尝试将数字转换为英语单词1234会成为 一千二百三十四 我的策略是这样的 将数字分成三位并将它们放入数组 finlOutPut 从右到左 转换每个组 每个单元格中finlOutPut数组 的三个数字到一个单词 这就是triCon
  • 在 xsl 中格式化科学数字表示形式

    我的 XML 中有以下值 1 8959581529998104E 4 我想将其格式化为使用 XSL 给我的确切数字 0 000189595815299981 format number 1 8959581529998104E 4 0 000
  • 如何根据 Haskell 中的区域设置格式化数字?

    在Python中我可以使用locale format根据区域设置漂亮地打印数字 gt gt gt import locale gt gt gt locale setlocale locale LC ALL en US UTF 8 en US
  • 使用 JavaScript 计算 A、B、C、D,而不是 0、1、2、3...

    这可能是一个不寻常的请求 但对于我的脚本 我需要一个按字母而不是数字递增的函数 例如 这是一个数字示例 var i 0 while condition window write We are at i i 本质上 我想像 Microsoft
  • 如何使用 jQuery 清空输入字段

    我在移动应用程序中 使用输入字段来命令用户提交号码 当我返回并返回到输入字段显示输入字段中显示的最新数字输入的页面时 有没有办法在每次加载页面时清除该字段 shares keyup function payment 0 calcTotal
  • 测试数字是否在循环区间内

    假设我们有一个数字圈 范围从 180 到 180 看起来像这样 180 180 90 90 0 圆的一部分始终沿顺时针方向扫过 如何判断一个数字是在扫描区间之内还是之外 在以下示例 I O 中 前两个数字表示间隔 第三个数字是正在检查的数字
  • C++ - 如何找到整数的长度

    我试图找到一种方法来查找整数的长度 位数 然后将其放入整数数组中 该作业还要求在不使用 STL 中的类的情况下执行此操作 尽管程序规范确实说我们可以使用 通用 C 库 我会问我的教授是否可以使用 cmath 因为我假设 log10 num
  • PHP 生成一个预先定义长度的随机数

    我正在尝试使用 mt rand 创建一个函数来生成真正的随机数 因为 rand 还不够 问题是我需要预先定义数字的长度 假设我需要一个 10 位随机数 无论如何 我一直在搞乱 这就是我想出的 function randomNumber le
  • 生成偶数随机数

    我需要一个代码来仅生成随机偶数 2 100网上有生成随机数的教程 但它们有奇数和偶数 请理解我只需要生成偶数 1 生成数字1 50 2 将所有数字乘以2 所有数字乘以 2 都是偶数
  • 如何使用 C# 对值进行数字排序?

    我有一个字符串 其中包含由句点分隔的数字 当我排序时 它看起来像这样 因为它是一个字符串 ascii 字符顺序 3 9 5 2 1 1 3 9 5 2 1 10 3 9 5 2 1 11 3 9 5 2 1 12 3 9 5 2 1 2 3
  • 使用 f:convertNumber 时设置小数点分隔符

    我想知道如何在 JSF 应用程序上设置默认的小数点分隔符 我有一些
  • 改进的 isNumeric() 函数?

    在一些项目中 我需要验证一些数据 并尽可能确定它是可用于数学运算的 JavaScript 数值 jQuery 和其他一些 javascript 库已经包含这样的函数 通常称为 isNumeric 还有一个发布在 stackoverflow
  • Insert 语句中的记录数 (Oracle)

    我想报告 Oracle 插入语句中插入的记录数 我是从语句插入的 因此我可以运行两次选择并进行计数 但我宁愿将其全部保留在一个语句中 有办法吗 在 PL SQL 中执行 INSERTSQL ROWCOUNT给出插入的行数 在 C 中执行 I
  • 使用 QuasirandomGenerator (对于傻瓜来说)

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

    今晚我一直在忙着学习 bash 我一直在尝试创建一个随机数字序列 该序列使用一个范围内的所有数字 并且每个数字只使用一次 因此 输入 1 5 的范围将输出 4 3 5 2 1 或 2 5 1 3 4 等 我在这件事上陷入了困境 Thanks
  • 从数组中打印素数

    我想用方法从数组中打印出所有素数 我可以用一个 int 来完成 但不知道如何从数组中返回某些数字 感谢帮助 public static boolean isPrime int tab boolean prime true for int i
  • Ruby 中的数字运算(需要优化)

    Ruby 可能不是最适合这种情况的语言 但我很乐意在我的终端中使用它 所以这就是我要使用的 我需要处理从 1 到 666666 的数字 因此我找出包含 6 但不包含 7 8 或 9 的所有数字 第一个数字是6 下一个16 then 26等等
  • 具有非常大的数字的除法

    我只是想知道在处理大数字时有哪些不同的除法策略 我所说的大数字是指 50 位数字 例如 9237639100273856744937827364095876289200667937278 82637448262718273966299344

随机推荐

  • 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