• 洛谷P2723 丑数 Humble Numbers


    P2723 丑数 Humble Numbers

      • 52通过
      • 138提交
    • 题目提供者该用户不存在
    • 标签USACO
    • 难度普及/提高-

      讨论  题解  

    最新讨论

    • 暂时没有讨论

    题目背景

    对于一给定的素数集合 S = {p1, p2, ..., pK},考虑一个正整数集合,该集合中任一元素的质因数全部属于S。这个正整数集合包括,p1、p1*p2、p1*p1、p1*p2*p3...(还有其它)。该集合被称为S集合的“丑数集合”。注意:我们认为1不是一个丑数。

    题目描述

    你的工作是对于输入的集合S去寻找“丑数集合”中的第N个“丑数”。所有答案可以用longint(32位整数)存储。

    补充:丑数集合中每个数从小到大排列,每个丑数都是素数集合中的数的乘积,第N个“丑数”就是在能由素数集合中的数相乘得来的(包括它本身)第n小的数。

    输入输出格式

    输入格式:

    第 1 行: 二个被空格分开的整数:K 和 N , 1<= K<=100 , 1<= N<=100,000.

    第 2 行: K 个被空格分开的整数:集合S的元素

    输出格式:

    单独的一行,输出对于输入的S的第N个丑数。

    输入输出样例

    输入样例#1:
    4 19
    2 3 5 7
    输出样例#1:
    27

    说明

    题目翻译来自NOCOW。

    USACO Training Section 3.1

    分析:一开始的思路是先把很多丑数求出来,然后排个序,输出第n个,但是由于n太大,而且没有范围,所以不行.

           优化一下,求出了第i-1个丑数,把所有可能的第i个丑数求出来,放到优先队列中,然后弹出最小的,这样的话要涉及到判重,TLE.

           换一种思路,为了找第i个丑数,那么一定要比第i-1个丑数大,而且是最小的那一个,打个表,可以发现比i-1大的丑数一定是比i-1小的丑数乘某个质数得到的,鉴于质数的数量很少,而丑数的数量很大,我们枚举质数,然后枚举丑数,直到大于第i-1个丑数,记录一下,找到所有的符合条件的丑数以后,找出最小值(也可以在寻找的途中更新最小值),那么这个最小值就是第i个丑数,不会超时.

    51分代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <map>
    #include <set>
    #include <queue>
    #include <functional>
    
    int k, n;
    long long s[110], ans[100010], tot;
    set <long long> m;
    priority_queue <long long, vector<long long>, greater<long long> >q;
    
    int main()
    {
        scanf("%d%d", &k, &n);
        for (int i = 1; i <= k; i++)
        {
            scanf("%lld", &s[i]);
            q.push(s[i]);
        }
        //q.push(1);
        while (tot <= n)
        {
            long long x = q.top();
            q.pop();
            //printf("%d
    ", x);
            if (!m.count(x))
            {
                ans[++tot] = x;
                m.insert(x);
            }
            for (int i = 1; i <= k; i++)
                q.push(s[i] * x);
            printf("%d
    ", tot);
        }
        printf("%lld", ans[n]);
        //while (1);
    
        return 0;
    }

    AC代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <map>
    #include <set>
    #include <queue>
    #include <functional>
    int pindex[110];
    int prime[110];
    int count;
    long long hum[1000001];
    
    int main(void)
    {
        int k, n;
        int i;
        int min, m;
        scanf("%d%d", &k, &n);
        for (i = 1; i <= k; i++) {
            scanf("%d", &prime[i]);
        }
        hum[count++] = 1;
        memset(pindex, 0, sizeof(pindex));
        while (count <= n) {
            min = 0x7FFFFFFF;
            for (i = 1; i <= k; i++) {
                while (prime[i] * hum[pindex[i]] <= hum[count - 1]) {
                    pindex[i]++;
                }
    
                if (prime[i] * hum[pindex[i]] < min)
                    min = prime[i] * hum[pindex[i]];
                }
            hum[count++] = min;
        }
    
        printf("%lld
    ", hum[n]);
        return 0;
    }
  • 相关阅读:
    C语言中的排序算法--冒泡排序,选择排序,希尔排序
    常见算法:C语言求最小公倍数和最大公约数三种算法
    提高软件测试效率的方法探讨
    面试官询问的刁钻问题——以及如何巧妙地应付它们
    软件测试面试--如何测试网页的登录页面
    如何衡量测试效率,如何提高测试效率!
    利用交叉测试提升软件测试效率
    交叉测试的必要性和遇到的问题
    敏捷测试
    HttpWatch工具简介及使用技巧
  • 原文地址:https://www.cnblogs.com/zbtrs/p/5936415.html
Copyright © 2020-2023  润新知