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;
}

posted @ 2018-09-22 19:36  ✡smy✡  阅读(114)  评论(0编辑  收藏  举报