P2527 [SHOI2001]Panda的烦恼
题目描述
panda是个数学怪人,他非常喜欢研究跟别人相反的事情。最近他正在研究筛法,众所周知,对一个范围内的整数,经过筛法处理以后,剩下的全部都是质数,不过panda对这些不感兴趣,他只对被筛掉的数感兴趣,他觉得在这些被筛掉的数中一定隐藏着重要的宇宙秘密,只是人们还没有发现罢了。
panda还觉得如果只是单纯地从小到大筛的话,还不足够发现其中的奥秘,于是他决定对至多只包含某些质因数的数进行研究(比如说至多只包含质因数2,3的数有2,3,4,6,8,9,……),他需要得到这些数中第k小的数(k是panda认为的宇宙系数),请你编个程序,帮助他找到这个数。
输入输出格式
输入格式:
第1行有2个数n,k,n代表质因数的个数,k代表那个宇宙系数(1<=n<=100,1<=k<=100000)
第2行有n个数,代表这n个质因数。(每个均小于1000,且不相同)
输出格式:
仅1行,即至多只包含这n个质因数的数中第k小的数。(这个数不会超过2000000000)
输入输出样例
输入样例#1:
2 7 3 5
输出样例#1:
45
说明
样例说明:前6个分别是3,5,9,15,25,27。
写了个队列,结果暴空间了、、、、


#include<queue> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define LL long long using namespace std; queue<LL>q; LL n,k,pre,sum,ans,a[1100]; LL read() { LL x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } int main() { n=read(),k=read(); for(int i=1;i<=n;i++) a[i]=read(),q.push(a[i]); while(!q.empty()&&sum<k) { LL x=q.front();q.pop(); if(x==pre) continue; sum++; ans=x; for(int i=1;i<=n;i++) q.push(x*a[i]); pre=x; } printf("%lld",ans); return 0; }
数组模拟队列
- 正常的想法是把乘出的数放入一个优先队列里,每次取出最小值和给出的 n 个素数相乘放入队列,再判一判重即可。时间复杂度大概为 k*log(2,n) ,其实处理得好也能过,优化一下空间即可,但是我不会处理,然后就 MLE 爆空间了。
- 鉴于 n 十分小,k 又十分大,而且发现 n*k 的时间也是可以的,于是就想想用普通数组来模拟出优先队列。我用了个
b[i]
来记录第i
个素数当前乘到了ans[]
中第几个数(好像是下一个应该乘的数),然后每次要加一个数到ans[]
中时,对每个素数乘一下它下一个要乘的,取出最小值,判一下重,如果无恙就放到ans[]
后面即可。 - 这样就保证了
ans[]
数组中的元素是单调递增的,而且不会跳元素。 - 具体一点,
ans[]
起初放个1
进去就可以了,最后得到 k 个数(不包括那个 1)就行了,输出第 k 个数。
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 110000 using namespace std; int n,k,s,minn,maxn,sum,ans[N],a[N],b[N]; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } int main() { n=read(),k=read(); for(int i=1;i<=n;i++) a[i]=read(); ans[0]=1; while(sum<k) { minn=0x7fffffff; for(int i=1;i<=n;i++) if(ans[b[i]]*a[i]<minn) minn=ans[b[i]]*a[i],s=i; b[s]++; if(minn!=ans[sum]) ans[++sum]=minn; } printf("%d",ans[k]); return 0; }