题目
对于一给定的素数集合 S = {p1, p2, …, pK}, 来考虑那些质因数全部属于S 的数的集合。这个集合包括,p1, p1p2, p1p1, 和 p1p2p3 (还有其它)。这是个对于一个输入的S的丑数集合。
注意:我们不认为1 是一个丑数。
你的工作是对于输入的集合S去寻找集合中的第N个丑数。longint(signed 32-bit)对于程序是足够的。
题解
堆
在a[i] (i=0) 里放1,每次用集合S里每个数乘a[i](i为循环变量),积插入a中 (a为小头堆) ,每插一次数都进行维护,并把数组中的第一个数删除,取出的第n个元素即为答案。(也可用大头堆做)
其他
方法还有很多,好好想吧
代码
var
k,n,i,j,t,m,x,y:longint;
a:array[1..1000000]of longint;
s:array[1..100]of longint;
procedure up(i,n:longint);
var
j,t:longint;
begin
if i=1 then exit;
j:=i div 2;
while j>1 do
begin
if a[i]<a[j] then
begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
end
else break;
i:=j;
j:=i div 2;
end;
end;
procedure down(i,n:longint);
var
j,t:longint;
begin
j:=i;
i:=i*2;
if i>n then exit;
repeat
if (a[i]>a[i+1])and(i<n) then inc(i);
if a[i]<a[j] then
begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
end
else break;
j:=i;
i:=i*2;
until i>n;
end;
begin
readln(k,n);
for i:=1 to k do
read(s[i]);
a[1]:=1;
t:=1;
for i:=1 to n do
begin
m:=a[1];
for j:=1 to k do
if int64(m)*s[j]<maxlongint then
begin
inc(t);
a[t]:=s[j]*m;
up(t,t);
end;
a[1]:=a[t];
dec(t);
down(1,t);
while a[1]=m do
begin
a[1]:=a[t];
dec(t);
down(1,t);
end;
end;
writeln(a[1]);
end.
以下是非堆做法,提交通过
var
a,b:array[1..100]of longint;
s:array[0..100000]of longint;
n,k:longint;
procedure init;
var
i:longint;
begin
readln(k,n);
for i:=1 to k do
read(a[i]);
end;
procedure main;
var
i,j,min,t,l:longint;
begin
s[0]:=1;l:=1;
for i:=1 to n do
begin
while true do
begin
min:=maxlongint;t:=0;
for j:=1 to k do
if s[b[j]]*a[j]<min then
begin
min:=s[b[j]]*a[j];
t:=j;
end;
inc(b[t]);
if l<>min then break;
end;
s[i]:=min;
l:=min;
end;
end;
begin
init;
main;
writeln(s[n]);
end.