1. 程式人生 > >Prime Gift

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