For a given set of K prime numbers S = {p1, p2, ..., pK}, consider the set of all numbers whose prime factors are a subset of S. This set contains, for example, p1, p1p2, p1p1, and p1p2p3 (among others). This is the set of `humble numbers' for the input set S. Note: The number 1 is explicitly declared not to be a humble number.
Your job is to find the Nth humble number for a given set S. Long integers (signed 32-bit) will be adequate for all solutions.
PROGRAM NAME: humble
INPUT FORMAT
Line 1: | Two space separated integers: K and N, 1 <= K <=100 and 1 <= N <= 100,000. |
Line 2: | K space separated positive integers that comprise the set S. |
SAMPLE INPUT (file humble.in)
4 19 2 3 5 7
OUTPUT FORMAT
The Nth humble number from set S printed alone on a line.
SAMPLE OUTPUT (file humble.out)
27
题意:给你 k 个素数,由这些素数作为因子,组成一系列的数称为丑数,求这些丑数中的第 n 大的数。
分析:打表d[n]。已经得出 k-1 个丑数,推第 k 个丑数。
策略一:首先对素数排序;对于每个素数 p,在[1,k-1]之间找出一个最小的丑数 h,满足d[i-1]<p*h,求出最小的满足条件的 p*h。减枝:查找采用二分,每次查找只需更新L,R可以不变。这样最坏的情况还是O(10^8)把所以案例跑完 1.3s 左右。
策略二:对于每个素数 p[i] ,找一个最小的丑数 h[j],满足d[k-1]<p[i]*h[j],也就说下次用判断素数 p[i]时,查找丑数是可以从h[j+1]开始判断。于是对每个素数p[i],使用一个index[i]来记录他已经判断到第index[i]个丑数了,下一次用p[i]判断是可以从 index[i]+1 开始判断。这个策略太很快了!!!(小技巧)
策略一:TLE
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/* ID: dizzy_l1 LANG: C++ TASK: humble */ #include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cstdio> #define MAXN 100001 #define MAXM 101 using namespace std; int a[MAXM]; long long d[MAXN]; int main() { freopen("humble.in","r",stdin); freopen("humble.out","w",stdout); int n,m,i,j,Min,t; bool flag; scanf("%d %d",&m,&n); for(i=1; i<=m; i++) scanf("%d",&a[i]); sort(a,a+m+1); d[0]=1; d[1]=a[1]; for(i=2; i<=n; i++) { Min=0x7fffffff; int M,L,R; flag=false; R=i-1; for(j=1; j<=m; j++) { L=0; while(L<=R) { M=(L+R)>>1; if(d[M]*a[j]>d[i-1]) R=M-1; else L=M+1; } if(L==i) t=d[i-1]*a[j],flag=true; else if(L<0) t=a[j],flag=true; else t=d[L]*a[j]; Min=min(Min,t); if(flag) break; } d[i]=Min; } printf("%lld\n",d[n]); return 0; }
策略二:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/* ID: dizzy_l1 LANG: C++ TASK: humble */ #include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cstdio> #define MAXN 100001 #define MAXM 101 using namespace std; int a[MAXM],p[MAXN],d[MAXN]; int main() { freopen("humble.in","r",stdin); freopen("humble.out","w",stdout); int n,m,i,j,k,Min; while(scanf("%d %d",&m,&n)==2) { for(i=0;i<m;i++) scanf("%d",&a[i]); d[0]=1;d[1]=a[0]; memset(p,0,sizeof(p)); for(i=2;i<=n;i++) { Min=0x7fffffff; for(j=0;j<m;j++) { while(a[j]*d[p[j]]<=d[i-1]) p[j]++; if(a[j]*d[p[j]]<Min) { Min=a[j]*d[p[j]]; k=j; } } d[i]=Min;p[k]++; } printf("%d\n",d[n]); } return 0; }