CF912E Prime Gift
看到\(n\)只有16,可以把这些质数分成两半,然后预处理出这些数相乘得出的小于\(10^{18}\)的所有数,排个序,然后二分最终答案,再用两个指针从前往后和从后往前扫,进行\(two-pointers\)统计答案是第几个,然后再搞搞救星了
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define db double
#define eps (1e-5)
using namespace std;
const int M=2000000+10;
const LL inf=1e18+1;
il LL rd()
{
re LL x=0,w=1;re char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int n;
LL a[2][10],k,b[2][M],t[2];
il void dfs(int x,int o,LL s)
{
if(a[x][o+1]) dfs(x,o+1,s);
LL ss=s;
while(inf/a[x][o]>=ss&&ss>0)
{
ss*=a[x][o];
b[x][++t[x]]=ss;
if(a[x][o+1]) dfs(x,o+1,ss);
}
}
int main()
{
n=rd();
for(int i=1;i<=n;i++) a[i&1][(i+1)>>1]=rd();
if(n>1) dfs(0,1,1);
dfs(1,1,1);
sort(b[0]+1,b[0]+t[0]+1),sort(b[1]+1,b[1]+t[1]+1);
b[0][0]=b[1][0]=1;
k=rd();
LL l=0,r=inf,ans=0;
while(l<=r)
{
LL mid=(l+r)>>1,kk=1;
for(int i=0,j=t[1];i<=t[0];i++)
{
while(j>=0&&(b[0][i]*b[1][j]<0||b[0][i]*b[1][j]>inf||b[0][i]*b[1][j]>=mid)) --j;
kk+=j+1;
}
if(kk<=k) ans=mid,l=mid+1;
else r=mid-1;
}
cout<<ans;
//hehhe
return 0;
}