[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]的数的集合。

然后我们可以合并集合。

f[i][j]=∑g[i-1][j-k]*p[i]k

g[i][j]=g[i-1][j]+f[i][j]

然后我们可以用函数式可并堆来维护所有的转移,在开一个全局的堆来维护所有的f。

然后一直弹堆顶就可以了。

注意pushdown

代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
int tot,prime[33],K,f[33][65],g[33][65];
ll n;
bool vis[130];
inline ll rd(){
    ll x=0;char c=getchar();bool f=0;
    while(!isdigit(c)){if(c==‘-‘)f=1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f?-x:x;
}
struct node{
    int i,j;ll val;
    node(int ii=0,int jj=0,ll v=0){i=ii;j=jj;val=v;}
    inline bool operator <(const node &b)const{return val<b.val;}
};
priority_queue<node>q;
struct tree{
    ll val,la;int l,r,d;
    tree(ll xx=0,ll yy=1,int lx=0,int rx=0,int dd=0){val=xx;la=yy;l=lx;r=rx;d=dd;}
}tr[16000002];
inline int newnode(int x,ll y){
    if(!x)return 0;
    int p=++tot;
    tr[p]=tr[x];tr[p].val=tr[p].val*y;tr[p].la=tr[p].la*y;
    return p;
}
inline void pushdown(int cnt){
    if(tr[cnt].la!=1){
        tr[cnt].l=newnode(tr[cnt].l,tr[cnt].la);
        tr[cnt].r=newnode(tr[cnt].r,tr[cnt].la);
        tr[cnt].la=1;
    }
}
int merge(int x,int y){
    if(!x||!y)return x|y;
    if(tr[x].val<tr[y].val)swap(x,y);
    pushdown(x);
    int p=newnode(x,1);
    tr[p].r=merge(tr[p].r,y);
    if(tr[tr[p].l].d<tr[tr[p].r].d)swap(tr[p].l,tr[p].r);
    tr[p].d=tr[tr[p].r].d+1;
    return p;
}
inline void prework(){
    int k;
    for(int i=2;i<=128;++i){
        if(!vis[i])prime[++prime[0]]=i;
        for(int j=1;j<=prime[0]&&(k=i*prime[j])<=128;++j){
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)break;
        }
    }
}
int main(){
    cin>>n>>K;
    prework();
    f[0][0]=g[0][0]=tot=tr[1].val=tr[1].la=1;
    for(int i=1;i<=prime[0];++i){
        f[i][0]=g[i][0]=1;
        for(ll pr=prime[i],j=1;pr<=n&&pr>0;++j,pr=pr*prime[i]){
            f[i][j]=0;
            for(ll prm=prime[i],k=1;k<=j;++k,prm=prm*prime[i]){
                f[i][j]=merge(f[i][j],newnode(g[i-1][j-k],prm));
            }
            g[i][j]=merge(g[i-1][j],f[i][j]);
            q.push(node(i,j,tr[f[i][j]].val));
        }
    }
    ll ans=0;
    while(K--){
        node x=q.top();q.pop();
        ans=x.val;
        pushdown(f[x.i][x.j]);
        f[x.i][x.j]=merge(tr[f[x.i][x.j]].l,tr[f[x.i][x.j]].r);
        q.push(node(x.i,x.j,tr[f[x.i][x.j]].val));
    }
    printf("%lld",ans);
    return 0;
} 

原文地址:https://www.cnblogs.com/ZH-comld/p/10446369.html

时间: 2024-09-30 15:25:28

[CQOI2016]伪光滑数的相关文章

【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

@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】伪光滑数

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

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

4524: [Cqoi2016]伪光滑数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 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^1

【CQOI 2016】伪光滑数

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

质数筛法详解

理论及实现 定义: 若一个正整数无法被除了1和它本身的之外的任何自然数整除,则称该为质数(素数),否则称该正整数为合数. 判定方法 试除法 引理: 若一个正整数\(N\)为合数,则存在一个能整除\(N\)的数\(T\)且\(2≤T≤ \sqrt N\) 证明就不再赘述,读者可以自行验证: 因此,我们只需要枚举\(2-\sqrt N\).只要这之中的所有数都不能被\(N\)整除,那么\(N\)就是质数了: #include<cmath> bool is_prime(int n) { if(n &

【CQOI2016纯净整合】BZOJ-4519~4524 (5/6)

感觉CQOI的难度挺好的,比较贴近自身,所以拿出来做了一下 CQOI2016 Day1 T1:不同的最小割 涉及算法:最小割/分治/最小割树 思路: 最小割树裸题,直接分治最小割,记录下答案,最后排序一下,统计不同的答案即可 CODE: #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace

CQOI2016游记

前情提要:我是丝薄,noip405的丝薄,所以这次省选特别虚 day0 上午随便切了两个题.背了下版. 下午看考场,环境还好.键盘也不错.评測姬非常好,就是人和人之间有点近,我回去买了耳塞(尽管并没实用上 晚上回去一边看板一边纠结,想自己万一进不了队怎么办,熬到十一点过最终睡了.我心态果然还是不够好啊,应该什么都不想的. day1 上午六点半就起来了,七点到学校.开车过去七点四十就到了重邮. 然后老师们讲了下比赛的注意事项,竟然要多存盘以防别人关错电脑233 然后就開始考试了. 一開始考试我就惊

《跨界杂谈》阿里和腾讯PK,华为消失了?

前言 本文内容纯属虚构,若有雷同纯属巧合.本文仅限于本人观点及本人认可的观点陈述,以及个人的一些无端揣测,(读者千万别当真).个别观点会缺少证据,文章也会缺乏逻辑.若给谁造成了伤害,麻烦告诉笔者,马上删除此文. 这又是一篇吃老本的文章,写于2014年3月7日,时隔一年,可能已今非昔比. 笔者第一次对阿里的重点关注是2007年-2009年,那时在一家互联网用户体验监测的公司任职,现在的流行词叫SaaS公司,那时还没这概念,工作职责之一就是长期监测国内主流互联网站的用户体验.关注用户体验当然也要关注