Prime Gift

题目描述

Jyt有n个质数,分别为p1,p2,p3…,pn。
她认为一个数x是优秀的,当且仅当x的所有质因子都在这n个质数中。
她想知道第k大的优秀的数是多少。保证答案不超过10e18。

题解

首先我们发现,p越小搜索量越大,一半的时候刚刚好能过,那么我们思考一下折半乱搞,奇偶搜索,分别记两个数组。然后看到答案这么大考虑二分答案,每次双指针扫有几个够的,注意最后可能一个区间内的都有这么多个,满足的时候要往前挤

代码

#include <bits/stdc++.h>
#define maxn 2000005
#define INF 1e18
#define LL long long
#define U unsigned long long
using namespace std;
inline int read(){
    int res,f=1; char c;
    while(!isdigit(c=getchar())) if(c=='-') f=-1; res=(c^48);
    while(isdigit(c=getchar())) res=(res<<3)+(res<<1)+(c^48);
    return res;
}
int n,m,a[maxn],cnt1,cnt2;
LL num[maxn],NUM[maxn];
void dfs(int x,LL now){
    num[++cnt1]=now;
    for(int i=x;i<=n;i+=2){
        if(now<=(long double)INF/a[i]) dfs(i,now*a[i]);
    }
}
void DFS(int x,LL now){
    NUM[++cnt2]=now;
    for(int i=x;i<=n;i+=2){
        if(now<=(long double)INF/a[i]) DFS(i,now*a[i]);
    }
}
int check(LL lim){
    LL tail=cnt2,sum=0;
    for(int i=1;i<=cnt1;i++){
        while(tail && NUM[tail]>(long double)lim/num[i]) tail--;
        if(!tail) break;sum+=tail;
    }
    return sum;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    dfs(1,1);
    DFS(2,1);
    sort(num+1,num+cnt1+1);
    sort(NUM+1,NUM+cnt2+1);
    U l=1,r=INF,mid;
    m=read();
    while(l<r){
        mid=l+r>>1;
        if(check(mid)>=m) r=mid;
        else l=mid+1;
    }
    cout<<l<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_32461955/article/details/83546569