zoukankan      html  css  js  c++  java
  • 【BZOJ-4524】伪光滑数 堆 + 贪心 (暴力) [可持久化可并堆 + DP]

    4524: [Cqoi2016]伪光滑数

    Time Limit: 10 Sec  Memory Limit: 512 MB
    Submit: 183  Solved: 82
    [Submit][Status][Discuss]

    Description

    若一个大于R的整数J的质因数分解有F项,其最大的质因子为ak,并且满足ak^k≤N,
    ak<128,我们就称整数J为N-伪光滑数。
    现在给出L,求所有整数中,第E大的N-伪光滑数。

    Input

    只有一行,为用空格隔开的整数L和E。
    2 ≤ N ≤ 10^18, 1 ≤ K ≤ 800000,保证至少有 E 个满足要求的数

    Output

    只有一行,为一个整数,表示答案。

    Sample Input

    12345 20

    Sample Output

    9167

    HINT

    Source

    Solution

    正解是可持久化可并堆+DP,抱歉,不会...于是采用乱搞的暴力做法..

    预处理出$<128$的全部质数,那么很显然,可以对数进行拆分了.

    考虑题目中所说的, 所以不妨枚举倍数,对于$prime[i]^{j}$,扔进堆中,但要维护的不只一个量

    然后从队首取K次即可,对于每次取出的数,除以它的最大质因子,乘上比他最大质因子小的最大的质数,再扔回堆中

    方便实现这些修改,不妨在堆中记录每个数data,最大值因子次数zs,较小一位的质数的坐标nt,最大值因子的下标mp

    启发:

    认真计算时间复杂度,在不会最优正解的情况下,也可以写出符合时间复杂度的暴力解

    类似的题目,多从质因数上考虑.实际上质数本身量较少,符合的质因子更少,所以效率会比较高效

    Code

    #include<iostream> 
    #include<cstdio> 
    #include<algorithm> 
    #include<queue> 
    using namespace std; 
    struct Node 
    { 
        long long data; int zs,nt,mp; 
        bool operator < (const Node & A) const
            {return data<A.data;} 
    }now,tmp;
    priority_queue <Node> q; 
    long long n,x; int k,j; 
    int prime[50]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127},cnt=31; 
    int main() 
    { 
        scanf("%lld%d",&n,&k);
        for (int i=1; i<=cnt; i++)  
            for (x=j=1; ; j++) 
                { 
                    x*=(long long)prime[i]; if (x>n) break;
                    tmp.data=x,tmp.zs=j,tmp.nt=i-1,tmp.mp=i;
                    //printf("%lld %d %d %d
    ",tmp.data,tmp.zs,tmp.nt,tmp.mp);
                    q.push(tmp);  
                } 
        while (k--) 
            { 
                now=q.top(); q.pop(); 
                if (now.zs>1) 
                    for (int i=now.nt; i; i--) 
                        {   
                            tmp.data=(long long)now.data/prime[now.mp]*prime[i]; tmp.zs=now.zs-1; tmp.nt=i; tmp.mp=now.mp; 
                            //printf("%lld %d %d %d
    ",tmp.data,tmp.zs,tmp.nt,tmp.mp);
                            q.push(tmp); 
                        } 
            } 
        printf("%lld
    ",now.data); 
        return 0; 
    }
  • 相关阅读:
    如何使用TestFlight进行Beta测试
    C语言与套接字
    ubuntu--- 【CUDA Toolkit Documentation】文档划重点
    ubuntu---【NVIDIA驱动 + CUDA 安装】不成功时的卸载方式
    ubuntu---CUDA版本与系统内核版本及GCC版本对应关系查询
    ubuntu---CUDA版本与NVIDIA显卡驱动版本对应关系查询
    ubuntu---NVIDIA驱动的多种安装方式
    OpenCV---安装完后,环境配置的几种方法
    ubuntu---查看系统CPU核数
    ubuntu---录屏工具Kazam
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5467682.html
Copyright © 2011-2022 走看看