题目描述 Description
对于一给定的素数集合 S = {p1, p2, ..., pK},
来考虑那些质因数全部属于S 的数的集合。这个集合包括,p1, p1p2, p1p1, 和 p1p2p3 (还有其它)。这是个对于一个输入的S的丑数集合。
注意:我们不认为1 是一个丑数。
你的工作是对于输入的集合S去寻找集合中的第N个丑数。longint(signed 32-bit)对于程序是足够的。
输入描述 Input Description
第 1 行: 二个被空间分开的整数:K 和 N , 1<= K<=100 , 1<= N<=100,000.
第 2 行: K 个被空间分开的整数:集合S的元素
输出描述 Output Description
单独的一行,写上对于输入的S的第N个丑数。
样例输入 Sample Input
4 19
2 3 5 7
样例输出 Sample Output
27
题解
先把1入堆,每次将堆中最小的数弹出,并把其*s[i]都入堆。
我的代码有考虑到同一个数重复入堆的情况,所以有特判。而且我的代码要三百多毫秒,有些大神只要几十毫秒,如果各位大神们有更快的程序,希望能留给我作参考。谢谢!
#include<cstdio> #include<cstring> #include<iostream> #include<cstdlib> #include<cmath> using namespace std; int n,m,zz=1,nn=1,count=0; long long sh[102],d[10000005],ans[100002]; void swap(int a,int b) {long long p=d[a]; d[a]=d[b]; d[b]=p;} void wh(int w) { int s; if((w<<1)<=nn&&d[w<<1]<d[w]) s=w<<1; else s=w; if(((w<<1)+1)<=nn&&d[(w<<1)+1]<d[s]) s=(w<<1)+1; if(s!=w) {swap(w,s); wh(s); } } void insert() { for(int i=1;i<=n;i++) {d[++nn]=d[1]*sh[i]; int j=nn; while(j>1&&d[j>>1]>d[j]) {swap(j>>1,j); j=j>>1;} } d[1]=d[nn]; nn--; wh(1); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&sh[i]); d[1]=1; while(true) {if(d[1]!=ans[zz-1]) {ans[zz]=d[1]; zz++; if(zz==m+2) {printf("%lld\n",ans[zz-1]); break;} insert(); } else {d[1]=d[nn]; nn--; wh(1);} //if(ans[zz]!=ans[zz-1]) count++; } //printf("%d %d\n",zz,nn); //for(int i=1;i<=nn;i++) printf("%d ",ans[i]); /*int i=1,j=1; while(j<m) {if(ans[i]!=ans[i]-1) j++; i++; }*/ return 0; }