習題:Prime Gift(折半搜尋)
阿新 • • 發佈:2020-07-20
題目
思路
這道題和折半搜尋有點類似
通過暴力可以算出
如果只有8個質數,在1e18內能表示的數的範圍不是很大
也就是指可以考慮將8個質數分成一組,另外8個質數分成一組
如果已知一個數
就可以用\(O(n*log_n)\)的時間去找出小於這個數一共有多少個數,即列舉一個集合,二分一個集合
用一個二分來列舉已知的數即可
總時間複雜度\(O(n*log_n*log_n)\)
程式碼
#include<iostream> #include<vector> #include<algorithm> using namespace std; int n,cnt; int p[20],c[20]; long long k; long long l=0,r=1e18,mid; vector<long long> s[2]; void dfs(int _ind,int la,long long now) { s[_ind].push_back(now); for(int j=la;j<=cnt;j++) if(1e18/c[j]>=now) dfs(_ind,j,now*c[j]); } long long check(long long mid) { long long ret=0; for(int i=0;i<s[0].size()&&s[0][i]<=mid;i++) { long long t=mid/s[0][i]; t=upper_bound(s[1].begin(),s[1].end(),t)-s[1].begin(); ret+=t; } return ret; } int main() { cin>>n; for(int i=1;i<=n;i++) cin>>p[i]; cin>>k; for(int i=1;i<=n;i++) if(i%2==0) c[++cnt]=p[i]; dfs(0,1,1); cnt=0; for(int i=1;i<=n;i++) if(i%2==1) c[++cnt]=p[i]; dfs(1,1,1); if(s[0].size()>s[1].size()) swap(s[0],s[1]); sort(s[0].begin(),s[0].end()); sort(s[1].begin(),s[1].end()); while(l+1<r) { mid=(l+r)>>1; if(check(mid)>=k) r=mid; else l=mid; } while(check(l+1)<k) l++; cout<<l+1; return 0; }