洛谷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\n", 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\n", 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\n", hum[n]);
    return 0;
}
时间: 2024-10-23 02:13:14

洛谷P2723 丑数 Humble Numbers的相关文章

洛谷P2723 丑数 Humble Numbers [2017年 6月计划 数论07]

P2723 丑数 Humble Numbers 题目背景 对于一给定的素数集合 S = {p1, p2, ..., pK},考虑一个正整数集合,该集合中任一元素的质因数全部属于S.这个正整数集合包括,p1.p1*p2.p1*p1.p1*p2*p3...(还有其 它).该集合被称为S集合的“丑数集合”.注意:我们认为1不是一个丑数. 题目描述 你的工作是对于输入的集合S去寻找“丑数集合”中的第N个“丑数”.所有答案可以用longint(32位整数)存储. 补充:丑数集合中每个数从小到大排列,每个丑

P2723 丑数 Humble Numbers

题意:给你k个质数,定义丑数集合为k个质数随机(1--k)个相乘得到的数 求第n小的丑数 暴力...貌似不太可行,(把所有大量丑数求出来,sort   QAQ) 可以想到,对于第i个丑数f[i],它一定是由之前的某个丑数*a[i]得到的 所以枚举之前已求出的丑数和a[i]相乘若>f[i-1] 则与ans取min 这些大于f[i-1]的所有值的min就是f[i]!(f[i]是大于f[i-1]的第一个数) #include<cstdio> #include<iostream> #

Luogu P2723 丑数 Humble Numbers

太巧妙了,想了好久都没想出来,居然只是道黄题... 用s[j]储存每个数的下界,以大大减少枚举次数:从较小的数据入手,分析解题思路,优化枚举顺序从而优化复杂度. 1 #include<iostream> 2 #include<climits> 3 4 using namespace std; 5 6 const int Maxn = 1e5+10; 7 int f[Maxn] = {1},p[110],s[110]; 8 int n,k,m; 9 10 int main(){ 11

Luogu2723丑数Humble Numbers

这是一道经典的归并排序题,100路归并,思路很简单,寻找最小值加入答案队列,然后把所有最小值的指针都前移(可能有重复的),直到答案队列的长度达到n,输出即可. 话说好像还有用堆的,我打了一个,结果最后一个点T了,估计是哈希函数没选好,开O3都没有(代码附下). 1 ///一百路归并 2 #include<cstdio> 3 #include<iostream> 4 using namespace std; 5 long long d[105],q[100001]; 6 int p[

洛谷1288 取数游戏II 博弈论

洛谷1288 取数游戏II 博弈论 最优策略 一定是你一步把值走完,然后我再走完,这样不给别人留后路 然后这样走 只要自己从左走 或者从右走其中有一个有奇数步可走,则说明是必胜局 如果都是只能走偶数步的,就是必败局 . 另一个题解 首先,对于一条链a1,a2,a3,a4......0 如果是偶数条边,那么现手一定赢,因为他每一次都只用把后面一条取完,例如 5 4 3 6 5 0 先手取完5,后手没法回到前一个位置,而无论接下来后手去多少,先手继续取完3,再然后取完5,后手没办法再去,先手赢.就这

洛谷 P1106 删数问题 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1106 题目描述 键盘输入一个高精度的正整数N,去掉其中任意k个数字后剩下的数字按原左右次序将组成一个新的正整数.编程对给定的N和k,寻找一种方案使得剩下的数字组成的新数最小. 输出应包括所去掉的数字的位置和组成的新的正整数.(N不超过250位) 输入数据均不需判错. 输入输出格式 输入格式: n (高精度的正整数) k (需要删除的数字

洛谷——P2421 A-B数对(增强版)

题目背景 woshiren在洛谷刷题,感觉第一题:求两数的和(A+B Problem)太无聊了,于是增加了一题:A-B Problem,难倒了一群小朋友,哈哈. 题目描述 给出N 个从小到大排好序的整数,一个差值C,要求在这N个整数中找两个数A 和B,使得A-B=C,问这样的方案有多少种? 例如:N=5,C=2,5 个整数是:2 2 4 8 10.答案是3.具体方案:第3 个数减第1 个数:第3 个数减第2 个数:第5 个数减第4 个数. 输入输出格式 输入格式: 第一行2 个正整数:N,C.

洛谷P1106 删数问题

题目描述 键盘输入一个高精度的正整数N,去掉其中任意k个数字后剩下的数字按原左右次序将组成一个新的正整数.编程对给定的N和k,寻找一种方案使得剩下的数字组成的新数最小. 输出应包括所去掉的数字的位置和组成的新的整数.(N不超过250位) 输入数据均不需判错. 输入输出格式 输入格式: n (高精度的正整数) k (需要删除的数字个数) 输出格式: 最后剩下的最小数. 输入输出样例 输入样例#1: 175438 4 输出样例#1: 13分析:贪心思想,我们每次删数肯定是要找前面的大数给删掉,并且这

洛谷 P1980 记数问题 2013年NOIP全国联赛普及组

3291 记数问题 2013年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解题目描述 Description试计算在区间1到n的所有整数中,数字x(0≤x≤9)共出现了多少次?例如,在1到11中,即在1.2.3.4.5.6.7.8.9.10.11中,数字1出现了4次. 输入描述 Input Description输入共1行,包含2个整数n.x,之间用一个空格隔开. 输出描述 Output Description输出共1行,包含一个整