习题:Prime Gift(折半搜索)
题目
思路
这道题和折半搜索有点类似
通过暴力可以算出
如果只有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;
}

浙公网安备 33010602011771号