数学算法:poweroj1026-丑数(根据固定倍数得到从小到大的序列)

题目:
1026: 丑数
Time Limit: 1000 MS Memory Limit: 65536 KB
Total Submit: 257 Accepted: 112 Page View: 1467
Submit Status Discuss
Description
丑数就是这个数的质因子只有2,3,5,7这四个,除此之外不再含有其它
别的质因子。

注意1也被认为是丑数.丑数的前20个为
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25, 27, ... ;
Input
每行输入一个N,1 <= N <= 5842,N为0时输入结束.
Output
输出相应的第N个丑数.
Sample Input
Raw
1
2
3
4
11
12
13
21
22
23
100
1000
5842
0
Sample Output
Raw
1
2
3
4
12
14
15
28
30
32
450
385875
2000000000
Source
SWUST




解题心得:
1、一开始想的是用一个数多次除尽2、3、5、7,最后能够得到1则是丑数,后来想了想,只要用1不停的乘上2、3、5、7就可以得到丑数,但是题目是对于第几个丑数的提问,所以我们需要对于得到的丑数进行一个排序,去重。但是由于数据量比较大,这样明显是不行的。所以需要在去重、排序的部分进行优化。
2、怎么优化呢,这里有一个很神奇的操作,就是把已经排好序的一个丑数列(这里直接用的1),(用1)乘上2、3、5、7,找出乘积中最小的,排在数列的最后面,然后再将之前选中的最小的那个数在数列中的位置向后移动一位,因为我们每次都是将最小的那个数放进数列之中,所以乘上2、3、5、7的部分和数列的最后一个相比只会等于或者大于它,等于的直接在位置中向后移动一位,大于的找出最小的放入,最后得到的就是一个有序的数列。


#include<bits/stdc++.h>
using namespace std;

long long Min(long long p1,long long p2,long long p3,long long p4)
{
    long long temp1,temp2;
    temp1 = min(p1,p2);
    temp2 = min(p3,p4);
    return min(temp1,temp2);
}
int main()
{
    int num[6000];
    num[1]= 1;
    long long p1=1,p2=1,p3=1,p4=1;
    int cnt = 1;
    while(cnt<=5842)
    {	//这里是核心算法,注意不能将if写成else if的形式,因为可能出现和最后一位重合的部分需要直接向后移动一位,也就是去重
        long long v = Min(num[p1]*2,num[p2]*3,num[p3]*5,num[p4]*7);
        if(v == num[p1]*2)
            p1++;
        if(v == num[p2]*3)
            p2++;
        if(v == num[p3]*5)
            p3++;
        if(v == num[p4]*7)
            p4++;
        num[++cnt] = v;
    }
    long long N;
    while(scanf("%lld",&N) && N)
        printf("%d\n",num[N]);
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值