问题描述
对于一给定的素数集合 S = {p1, p2, …, pK}, 来考虑那些质因数全部属于S 的数的集合。这个集合包括,p1, p1p2, p1p1, 和 p1p2p3 (还有其它)。这是个对于一个输入的S的丑数集合。
注意:我们不认为1 是一个丑数。
你的工作是对于输入的集合S去寻找集合中的第N个丑数。longint(signed 32-bit)对于程序是足够的。
输入
第 1 行: 二个被空格分开的整数:K 和 N , 1<= K<=100 , 1<= N<=100,000.
第 2 行: K 个被空格分开的整数:集合S的元素
输出
单独的一行,写上对于输入的S的第N个丑数。
样例输入
4 19
2 3 5 7
样例输出
27
算法讨论
丑数就是因子在S集合里的数,那么我们就先将1放入数组,构建堆,然后拿堆里最小的数去乘S集合里的数放入数组,每次乘完就插入小顶堆中,注意去重。最后到n+1是乘出来的数就是第n大的丑数。
const
maxn=300000;
var
a:array[1..maxn] of longint;
b:array[1..100] of longint;
i,j,n,k,l:longint;
t:int64;
procedure siftup(i:longint);
var
t:longint;
begin
if i=1
then exit;
while i>1 do
begin
if a[i]<a[i div 2]
then begin
t:=a[i];
a[i]:=a[i div 2];
a[i div 2]:=t
end
else break;
i:=i div 2
end;
end;
procedure siftdown(i:longint);
var
t:longint;
begin
if i*2>l
then exit;
while i*2<=l do
begin
i:=i*2;
if (i+1<=l) and (a[i+1]<a[i])
then i:=i+1;
if a[i div 2]>a[i]
then begin
t:=a[i];
a[i]:=a[i div 2];
a[i div 2]:=t
end
else break
end;
end;
procedure insert(i:longint);
begin
inc(l);
a[l]:=i;
siftup(l)
end;
procedure delete(i:longint);
var
x,y:longint;
begin
x:=a[i];
y:=a[l];
dec(l);
if i=l+1
then exit;
a[i]:=y;
if y>=x
then siftdown(i)
else siftup(i)
end;
begin
read(k,n);
for i:=1 to k do
read(b[i]);
a[1]:=1;
l:=1;
for i:=1 to n+1 do
begin
t:=a[1];
for j:=1 to k do
if t*b[j]<maxlongint
then insert(t*b[j]);
delete(1);
while a[1]=t do
delete(1)
end;
write(t)
end.
Pixiv ID:58623537