【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\n",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\n",tmp.data,tmp.zs,tmp.nt,tmp.mp);
                        q.push(tmp);
                    }
        }
    printf("%lld\n",now.data);
    return 0;
}
时间: 2024-11-09 22:12:26

【BZOJ-4524】伪光滑数 堆 + 贪心 (暴力) [可持久化可并堆 + DP]的相关文章

@bzoj - [email&#160;protected] [Cqoi2016]伪光滑数

目录 @description@ @[email protected] @version - [email protected] @version - [email protected] @accepted [email protected] @[email protected] @description@ 若一个大于 1 的整数 M 的质因数分解有 k 项,其最大的质因子为 \(A_k\),并且满足 \(A_k^k \le N\),\(A_k < 128\),我们就称整数 M 为 N - 伪光

【BZOJ4524】[Cqoi2016]伪光滑数 堆(模拟搜索)

[BZOJ4524][Cqoi2016]伪光滑数 Description 若一个大于1的整数M的质因数分解有k项,其最大的质因子为Ak,并且满足Ak^K<=N,Ak<128,我们就称整数M为N-伪光滑数.现在给出N,求所有整数中,第K大的N-伪光滑数. Input 只有一行,为用空格隔开的整数N和K 2 ≤ N ≤ 10^18, 1 ≤ K ≤ 800000,保证至少有 K 个满足要求的数 Output 只有一行,为一个整数,表示答案. Sample Input 12345 20 Sample

bzoj4524【CQOI2016】伪光滑数

4524: [Cqoi2016]伪光滑数 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 257  Solved: 117 [Submit][Status][Discuss] Description 若一个大于R的整数J的质因数分解有F项,其最大的质因子为ak,并且满足ak^k≤N, ak<128,我们就称整数J为N-伪光滑数. 现在给出L,求所有整数中,第E大的N-伪光滑数. Input 只有一行,为用空格隔开的整数L和E. 2 ≤ N ≤ 1

[CQOI2016]伪光滑数

题目描述 若一个大于1的整数M的质因数分解有k项,其最大的质因子为Ak,并且满足Ak^K<=N,Ak<128,我们就称整数M为N-伪 光滑数.现在给出N,求所有整数中,第K大的N-伪光滑数. 题解 题面的k意思是将这个数质因数分解后所有的质因子的指数和. 我们先把128以内的所有素数找出来,然后做一个dp. 我们令dp[i][j]表示当前数的最大的质因子为p[i],当前所有素因子的指数和为j的数的集合. 我们再令g[i][j]表示当指数和位j时,所有最大质因子小于等于p[i]的数的集合. 然后

【BZOJ】1028: [JSOI2007]麻将(贪心+暴力)

http://www.lydsy.com/JudgeOnline/problem.php?id=1028 表示不会贪心QAQ 按顺序枚举,如果能形成刻子那么就形成刻子,否则形成顺子.orz 证明?:因为按顺序枚举,所以当枚举到i,i一定要用完,所以因为>3个顺子和>3个刻子等价,所以考虑<3个顺子.如果i是刻子,假设我们用顺子,那么显然会剩下<=2个,因此不是最优的,所以有刻子就用刻子. 那么暴力枚举添加的,然后暴力枚举哪个是对子,最后暴力判断..n^3.. #include &l

【CQOI 2016】伪光滑数

Solution 又是一道神仙题.蒟蒻表示不看题解根本不会做 首先我们定义一个 DP 数组 \(\mathtt{f[i][j]}\) 表示:最大质因子为 \(\mathtt{p[i]}\),分解成 j 个质数(可以相同)组成的集合(其中 \(\mathtt{f[i][j]}\) 是这个集合的根节点,在这里我们用左偏树).我们知道,只要得到了这个 DP,我们就可以把这个玩意儿的权值塞进队列排序,再插入儿子进行查询. 为了求得这个数组,我们需要再定义一个 \(\mathtt{g[i][j]}\) 表

BZOJ 1029: [JSOI2007]建筑抢修 堆+贪心

1029: [JSOI2007]建筑抢修 Description 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是T部落的基地里已经有N个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建筑设施将会完全毁坏.现在的情况是:T部落基地里只有一个修理工人,虽然他能瞬间到达任何一个建筑,但是修复每个建筑都需要一定的时间.同时,修理工人修理完一个建筑才能修理下一个建筑,不能同时修理多个建筑.如果某个建筑在一段时间之内没有完全修理完毕,这

POJ3253 Fence Repair 小顶堆+贪心

给了你N个木棒,求把他们组装成一根需要的最小花费,每次只能选两根组装在一起,需要的花费为两个木棒之和, 以前遇到过把一整根切开的,那个是DP,这个则有些类似,可是大胆的猜测了一下,直接每次选取所有木棒中最短的两根,这样就可以了,那么贪心是适用的,但是数量很多,而且两根最短的组装好了得插回去,这样不可能每次都排序吧, 这题首先优先队列肯定是可以做的, 最小堆也是可以的,每次都选出堆里的最小的两个求和再放回去即可 队列本身也就是堆吧,所以差别不大,但是没用过最小堆最大堆的 所以用一次把 #inclu

P4053 [JSOI2007]建筑抢修 堆贪心

思路:堆贪心 提交:1次 题解: 先按时间\(sort\),然后如果能修就直接扔堆里,不能修取堆顶比一下时间长短,把时间短的扔进堆: #include<cstdio> #include<iostream> #include<queue> #include<algorithm> #define ull unsigned long long #define ll long long #define R register int using namespace s