例题5-7 丑数 UVa136
感悟。
1、从网站下载英文原题,没想到内容半页不到,很快读懂,菜题一个。
2、基本思路,能被2整除,一直除2;能被3整除,一直除3;能被5整除,一直除5;最后值为1,则为丑数。
3、编好提交http://vjudge.net,Time limit exceeded,菜题不菜,感受到竞赛题的威力。
4、用printf("Time used = %.2f\n",(double)clock()/CLOCKS_PER_SEC);测试时间23.21s,
5、这个思路http://blog.youkuaiyun.com/synapse7/article/details/11664577有点牛:可以用暴力先把答案算出来。
6、http://vjudge.net提交WA,一查,少了最后一个.号,修改,提交AC,在https://uva.onlinejudge.org/提交AC,看看时间,2016-11-17 18:39
7、对此题一直念念不忘,一丝想法飘过,set集合中元素不可重复,非1丑数,丑数/2或丑数/3或丑数/5必是丑数,马上编码,应该代码量很小,耗时明显较短。但上机一调试,耗时巨大。
8、通过http://www.cnblogs.com/flyoung2008/articles/2136485.html
http://www.cnblogs.com/void/archive/2012/02/01/2335224.html
http://blog.youkuaiyun.com/rushkid02/article/details/7687125
三篇博客学习了优先队列,效果还不错。
9、点评书中代码,写点不一样的地方:
一、因每次插入2x,3x,5x,故用int必越界,所以用long long,typedef方便原因有2,1是定义变量书写代码方便,2是方便测试,如typedef int LL;
二、因要查找队列中的元素,队列没有提供专门方法,故用set进行中转,所以set不能省;
三、将2,3,5放在整数数组中,写起代码for循环就搞定,不用2写一次,3写一次,5写一次。
四、因为处理的数据都是丑数,不存在非丑数的计算,所以运算量小了许多许多,所以写出的代码才能通过测试。
附上AC代码,编译环境Dev-C++4.9.9.2
#include <cstdio>
int main(){
printf("The 1500'th ugly number is 859963392.\n");
}
以上AC代码的答案,来自Time limit exceeded代码,如下:
#include <iostream>
//#include <ctime>
//#include <cstdio>
using namespace std;
int main(){
int i=0;
int ans;
int count=0;
while(1){
i++;
ans=i;
while(ans%2==0){
ans/=2;
}
while(ans%3==0){
ans/=3;
}
while(ans%5==0){
ans/=5;
}
if(ans==1){
count++;
}
if(count==1500)
break;
}
cout<<"The 1500'th ugly number is "<<i<<endl;
// printf("Time used = %.2f\n",(double)clock()/CLOCKS_PER_SEC);
return 0;
}
两个代码造就了AC程序。此时2016-11-17 18:33
附上消化书中写的AC代码。
#include <iostream>
#include <queue>
#include <set>
using namespace std;
typedef long long LL;
int main(){
LL x,x2;
priority_queue<LL,vector<LL>,greater<LL> > pq;
set<LL> s;
int i;
int coeff[3]={2,3,5};
int j;
pq.push(1);
s.insert(1);
for(i=1;;i++){
x=pq.top();
pq.pop();
if(i==1500){
cout<<"The 1500'th ugly number is "<<x<<"."<<endl;
break;
}
for(j=0;j<3;j++){
x2=x*coeff[j];
if(!s.count(x2)){
s.insert(x2);
pq.push(x2);
}
}
}
return 0;
}