丑数【思维题】

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个丑数.


题目链接

  这道题是有简单的做法O(N * log(N)),就是用优先队列之类的堆来优化,因为这里的N是比较的小的。所以,直接暴力搞当然是没有问题的,现在来介绍一种O(N)级别的强效算法。

  我们不妨直接一个个的来确定答案,譬如说,ans[1] = 1这个是必要条件,就像数学归纳法中确定a(1)的做法是一样的。

  那么,下一步一定是* 2* 3* 5* 7,选择哪个呢?那么,1之后就有2、3、5、7四种选择,好,很明显的选2,就是由1 * 2得到的,接下去,我们令“* 2”指针指向ans[2],因为它已经和ans[1]做过乘法了。

  以此类推,在代码上是这样写到(因为我担心我讲不清楚):

inline void init()
{
    ans[1] = 1;
    fill(p, p + 4, 1);
    ll val;
    for(int i=2; i<=maxN; i++)
    {
        val = MIN_4(ans[p[0]] * 2LL, ans[p[1]] * 3LL, ans[p[2]] * 5LL, ans[p[3]] * 7LL);
        if(val == ans[p[0]] * 2LL) p[0]++;
        if(val == ans[p[1]] * 3LL) p[1]++;
        if(val == ans[p[2]] * 5LL) p[2]++;
        if(val == ans[p[3]] * 7LL) p[3]++;
        ans[i] = val;
    }
}

好了,将答案预处理出来,剩下的就是O(1)的输出了,如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MIN_4(a, b, c, d) min(min(a, b), min(c, d))
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 5842;
ll ans[maxN + 1];
int p[4];
inline void init()
{
    ans[1] = 1;
    fill(p, p + 4, 1);
    ll val;
    for(int i=2; i<=maxN; i++)
    {
        val = MIN_4(ans[p[0]] * 2LL, ans[p[1]] * 3LL, ans[p[2]] * 5LL, ans[p[3]] * 7LL);
        if(val == ans[p[0]] * 2LL) p[0]++;
        if(val == ans[p[1]] * 3LL) p[1]++;
        if(val == ans[p[2]] * 5LL) p[2]++;
        if(val == ans[p[3]] * 7LL) p[3]++;
        ans[i] = val;
    }
}
int main()
{
    init();
    int x;
    while(scanf("%d", &x) && x)
    {
        printf("%lld\n", ans[x]);
    }
    return 0;
}

 

你可能感兴趣的:(思维)