zoukankan      html  css  js  c++  java
  • 入门OJ 1126【丑数】

    描述

    对于一给定的素数集合 S = {p1, p2, ..., pK},如果一个数字,当我们对其做完质因子分解后,其质因子全是来自我们给定的素数集合,则认为这个数字是个丑数。
    注意:我们不认为1 是一个丑数。 
    你的工作是对于输入的集合S去寻找第N个丑数。

    输入输出格式

    输入

    第 1 行: 二个被空间分开的整数:K 和 N , 1<= K<=100 , 1<= N<=100,000. 
    第 2 行: K 个被空间分开的整数:集合S的元素

    输出

    第N个丑数。.

    输入输出样例

    输入样例

    4 19
    2 3 5 7

    输出样例

    27
    

    解题思路

      首先想到的就是一个一个慢慢计算上去,但是肯定会超时,果断放弃,然后用了队列,每次取出队头,然后一个一个乘集合里的数,但是发现这个没按大小顺序排列,所以又WA了。然后,一种很神奇的东西——优先队列出现了:

      优先队列是经过一系列玄学的操作,让优先级高的先出列

      priority_queue<int> q;通过操作,按照元素从大到小的顺序出队

      priority_queue<int,vector<int>, greater<int> > q;通过操作,按照元素从小到大的顺序出队

      本题果断选第二种。注意,这里不再用q.front()而是用q.top()取队首元素。

      然后呢,你就会发现,2*3和3*2重复了,这可怎么办呢?打标记吗?但是我嫌太麻烦,聪明的我果断选择了另一种方式:

      那么我们推一推可能会发现,我们让每一个取出的元素乘质数时从小到大,如果取出的元素%这个质数=0,那么就乘完这个质数就不继续向后乘了(因为某个质数的k次方也是丑数,所以要放进去)。每一个存进去的数字,都是从小到大乘过来的,就可以避免重复,于是可以优化一个logn的复杂度。最后在循环到第n次时,取出来的便是第n小的,即第n个丑数。

    题解

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,k,ans; 
     4 int s[10001];//存集合 
     5 priority_queue<long long, vector<long long>, greater<long long> > q;//优先队列 
     6 int main()
     7 {    
     8     cin>>n>>k;//我把n和k反着存的 
     9     for(int i=1;i<=n;i++)
    10     {
    11         cin>>s[i];    
    12         q.push(s[i]);//进队列 
    13     }
    14     for(int i=1;i<=k;i++)
    15     {
    16         long long head=q.top();//取队头 
    17         q.pop();//弹出 
    18         if(i==k)cout<<head;//第k小就输出 
    19         for(int j=1;j<=n;j++)
    20         {
    21             q.push(head*s[j]);//进队列 
    22             if(head%s[j]==0)//去重 
    23             break;
    24         }
    25     }
    26     return 0;
    27 }
  • 相关阅读:
    Linux .下Apache的安装
    从程序员到项目经理:项目管理三大目标
    linux下mysql安装
    Linux学习之常用命令
    转载:struts2拦截器
    el自定义函数库
    JAVA正则表达式小结
    JSP自定义标记
    JAVA动态代理(JDK和CGLIB)
    JAVA反射机制
  • 原文地址:https://www.cnblogs.com/hualian/p/11184679.html
Copyright © 2011-2022 走看看