• CF912E Prime Gift


    题目大意

    给定一个大小为 n 的素数集合
    求出分解后只含这些质数因子的第 k 小整数
    题目链接

    题解

    在n这么小的情况下,肯定优先考虑暴搜
    可是爆搜显然空间开不下,
    那我们想想来如何优化这个暴搜,meet-in-the-middle!!!
    把整个素数集合分成两半,分别记录下每一部分元素可以组合出的所有小于 1E18 的数
    然后再二分答案,每次check过程中合并这两个集合中的元素,找到比 mid 小的个数就行了

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define re register
    #define int long long
    #define in inline
    #define get getchar()
    #define pb push_back
    in int read()
    {
    	int t=0; char ch=get;
    	while( ch<'0' || ch>'9') ch=get;
    	while(ch<='9' && ch>='0') t=t*10+ch-'0', ch=get;
    	return t;
    }
    const int maxn=1e18;
    const int _=1e3+5;
    vector<int> v[3];
    int n,p[_],sums=0;
    in void dfs(int k,int i,int mul)
    {
    	if(i>n)
    	{
    		v[k].pb(mul);
    		return ;
    	}
    	for(re int qwe=1;;qwe*=p[i])
    	{
    		dfs(k,i+2,mul*qwe);
    		if(mul*qwe>maxn/p[i])return;
    	}
    }
    
    signed main()
    {
    	n=read();
    	v[1].pb(0),	v[2].pb(0);
    	for(re int i=1;i<=n;i++)
    		p[i]=read();
    	int k=read();
    	dfs(1,1,1);dfs(2,2,1);
    	sort(&v[1][1],&v[1][v[1].size()]);
    	sort(&v[2][1],&v[2][v[2].size()]);
    	int l=0,r=maxn,ans=0,len1=v[1].size()-1,len2=v[2].size()-1;
    	while(l<=r)
    	{
    		int mid=l+r>>1,res=0;
    		for(re int i=1,j=len2;j>=1&&i<=len1;res+=j,i++){
    			while(j&&v[2][j]>mid/v[1][i]) j--;
    		}
    		if(res<k) l=mid+1;
    		else r=mid-1,ans=mid;
    	}
    	cout<<ans<<endl;
    }
    
    
  • 相关阅读:
    SpringBoot进阶教程(六十七)RateLimiter限流
    Nginx限流配置
    ab test压力测试
    Nginx负载均衡配置
    arduino串口通信
    flask文件路径设置问题
    WIN10和ubunu共享文件夹相互访问
    树莓派录音和播放声音
    深度学习论文翻译解析(十六):Squeeze-and-Excitation Networks
    人工智能必备数学基础:高等数学基础(2)
  • 原文地址:https://www.cnblogs.com/yzhx/p/11742257.html
走看看 - 开发者的网上家园