1278. 【USACO题库】3.1.3 Humble Numbers丑数

题目描述

对于一给定的素数集合 S = {p1, p2, ..., pK}, 

来考虑那些质因数全部属于S 的数的集合。这个集合包括,p1, p1p2, p1p1, 和 p1p2p3 (还有其它)。这是个对于一个输入的S的丑数集合。

注意:我们不认为1 是一个丑数。

你的工作是对于输入的集合S去寻找集合中的第N个丑数。longint(signed 32-bit)对于程序是足够的。


PROGRAM NAME: humble


INPUT FORMAT














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


SAMPLE INPUT (file humble.in) 

4 19

2 3 5 7


OUTPUT FORMAT

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


SAMPLE OUTPUT (file humble.out)

27



输入
输出
样例输入
 
      
样例输出
 
      
数据范围限制

水水水水水水水水水!
淼淼淼!
一,暴力。33.3分
二,宽搜。但2*5=5*2=10,值会重复出现,很难处理。33.3~100分
三,堆!堆可以维护最小值,依次输出堆顶。对于重复,判断目前堆顶是否
等于上一个堆顶be,等于继续down,直到不等于为止。
而且宽搜第i个状态不一定最小,确定不了宽搜边界,堆没有该问题。
标程(请勿抄袭):
var
        i:longint;
        j,k,m,n,o,p,l,s,t,len,before:int64;
        a,f:array[0..10000000] of int64;
procedure up(x:int64);
begin
        while (x>0) and (a[x]<a[x div 2]) do begin
                t:=a[x];
                a[x]:=a[x div 2];
                a[x div 2]:=t;
                x:=x div 2;
        end;
end;
procedure down(x:int64);
var
        xx,yy:int64;
begin
        while ((x*2<len) and (a[x*2]<a[x])) or ((x*2+1<len) and (a[x*2+1]<a[x])) do begin
                xx:=x*2;
                yy:=x*2+1;
                if a[xx]<a[yy] then begin
                        t:=a[x];
                        a[x]:=a[xx];
                        a[xx]:=t;
                        x:=xx;
                end else begin
                        t:=a[x];
                        a[x]:=a[yy];
                        a[yy]:=t;
                        x:=yy;
                end;
        end;
end;
begin
        
        readln(n,k);
        for i:=1 to n do read(f[i]);
        for i:=1 to n do begin
                a[i]:=f[i];
                up(i);
        end;
        len:=n;
        l:=0;
        before:=0;
        repeat
                inc(l);
                if a[1]=before then begin
                        repeat
                                a[1]:=a[len];
                                down(1);
                                dec(len);
                        until a[1]<>before;
                end;
                before:=a[1];
                for i:=1 to n do begin
                        inc(len);
                        a[len]:=a[1]*f[i];
                        up(len);
                end;
                //writeln(a[1]);
                {for j:=1 to len do begin
                        if a[j]=a[1] then begin
                                a[j]:=a[len];
                                down(j);
                                dec(len);
                        end;
               end;  }
        until l=k;
        writeln(a[1]);
        close(input);close(output);
end.


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值