题解

可持久化可并堆

用\(f[i,j]\)表示最大的质数标号为i,然后有j个质数乘起来

用\(g[i,j]\)表示\(\sum_{k = 1}^{i}f[k,j]\)

转移是

\(f[i,j] = \sum_{k= 1}^{j} g[i - 1,j - k] * p_{i}^{k}\)

\(g[i,j] += f[i,j]\)

这就要资瓷两个集合的合并了

可是集合显然非常大,我们可以用可持久化来帮助完成这件事,就完成了

代码

#include <bits/stdc++.h>
#define enter putchar('\n')
#define space putchar(' ')
#define pii pair<int,int>
#define fi first
#define se second
#define MAXN 1000005
#define pb push_back
#define mp make_pair
#define eps 1e-8
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
int64 N;
int K,prime[105],tot;
bool nonprime[205];
int64 pw[105];
struct node {
node *lc,*rc;
int64 mul,val;
int dis;
}pool[17000000],*tail = pool;
struct set_node {
int64 val;node *rt;
set_node(){}
set_node(int64 _v,node *r) {
val = _v;rt = r;
}
friend bool operator < (const set_node &a,const set_node &b) {
return a.val > b.val;
}
friend bool operator == (const set_node &a,const set_node &b) {
return a.val == b.val && a.rt == b.rt;
}
};
node *g[105],*f[105];
set<set_node > S;
node *Newnode(int64 v) {
node *res = tail++;
res->mul = 1;res->val = v;
res->lc = res->rc = NULL;
res->dis = 0;
return res;
}
int getdist(node *p) {
return p ? p->dis : -1;
}
node* addlazy(node *u,int64 val) {
if(!u) return NULL;
node *res = tail++;
*res = *u;
res->val *= val;
res->mul *= val;
return res;
}
void push_down(node *&u) {
if(u->mul != 1) {
u->lc = addlazy(u->lc,u->mul);
u->rc = addlazy(u->rc,u->mul);
u->mul = 1;
}
}
node *Merge(node *A,node *B) {
if(!A) return B;
if(!B) return A;
if(A->val < B->val) swap(A,B);
push_down(A);
node *res = tail++;
*res = *A;
res->rc = Merge(A->rc,B);
if(getdist(res->rc) > getdist(res->lc)) swap(res->lc,res->rc);
res->dis = getdist(res->rc) + 1;
return res;
}
void Solve() {
read(N);read(K);
for(int i = 2 ; i <= 128 ; ++i) {
if(!nonprime[i]) {
prime[++tot] = i;
for(int j = 2 ; j <= 128 / i ; ++j) {
nonprime[i * j] = 1;
}
}
}
for(int i = 0 ; i <= 100 ; ++i) g[i] = NULL;
g[0] = Newnode(1);
for(int i = 1 ; i <= tot ; ++i) {
int cnt = 0;int64 t = N;
while(t >= prime[i]) {t /= prime[i];++cnt;}
pw[0] = 1;
for(int k = 1 ; k <= cnt ; ++k) pw[k] = pw[k - 1] * prime[i];
for(int k = 1 ; k <= cnt ; ++k) {
f[k] = NULL;
for(int h = 1 ; h <= k ; ++h) {
f[k] = Merge(f[k],addlazy(g[k - h],pw[h]));
}
}
for(int k = 1 ; k <= cnt ; ++k) g[k] = Merge(g[k],f[k]);
}
node *rt = NULL;
for(int i = 1 ; i <= 100 ; ++i) rt = Merge(rt,g[i]);
S.insert(set_node(rt->val,rt));
for(int i = 1 ; i < K ; ++i) {
set_node p = *S.begin();
S.erase(S.begin());
push_down(p.rt);
if(p.rt->lc) S.insert(set_node(p.rt->lc->val,p.rt->lc));
if(p.rt->rc) S.insert(set_node(p.rt->rc->val,p.rt->rc));
while(S.size() > K - i) S.erase(--S.end());
}
out((*S.begin()).val);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}

最新文章

  1. tomcat配置
  2. css之颜色值、单位
  3. 【积累】发送验证码按钮倒计时js
  4. iOS开发笔记之Runtime实用总结
  5. BZOJ1315 : Ural1557Network Attack
  6. [linux系统]--Sed
  7. [实变函数]2.1 度量空间 (metric space), $n$ 维 Euclidean 空间
  8. 深入浅出ES6(一):ES6是什么
  9. 线程以及数据对象的wait()和notifyAll()方法
  10. JUnit三分钟教程 ---- 实际应用
  11. Lu核心库系统结构及输出函数
  12. String类重写
  13. Spring 5.0.0.RC1 - CORS Support 【译文】
  14. Linux内核互斥锁--mutex
  15. java如何输入数据
  16. 大神教你如何解决Linux系统80端口被占用
  17. Codeforces Round 1152 (div. 2)
  18. Python游戏编程入门3
  19. cocos Studio使用问题
  20. leetcode 921. 使括号有效的最少添加(Python)

热门文章

  1. Hadoop生态圈-Hive的自定义函数之UDAF(User-Defined Aggregation Function)
  2. 视音频数据处理入门:PCM音频采样数据处理
  3. linux diff 命令
  4. 如何在Mongodb中实现数据超时自动删除功能?
  5. jvm内存模型(运行时数据区)
  6. bzoj千题计划159:bzoj2055: 80人环游世界(有源汇上下界可行最小费用流)
  7. python 三种遍历列表里面序号和值的方法
  8. 2016-2017-20155329 《Java程序设计》第5周学习总结
  9. 20155217 2016-2017-2 《Java程序设计》第4周学习总结
  10. 最大团 HDU-1530