Bzoj 4524 [Cqoi2016]伪光滑数(堆)

题面

题解

先筛出$<128$的质数,很少,打个表即可

然后钦定一个质数最大,不断替换即可(丢进大根堆里面,然后取出一个,替换在丢进去即可)

具体来说,设一个四元组$[t,x,y,z]$表示当前的总乘积为$t$,$x$为最大的质数,$y$表示为$x$的多少次方,最后一个$z$表示当前能枚举的右界。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using std::priority_queue;
typedef long long ll;

template<typename T>
void read(T &x) {
    int flag = 1; x = 0; char ch = getchar();
    while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
    while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
}

ll N;
int K, p[] = {1, 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};
struct Node { ll t; int x, y, z; };
bool operator < (const Node &a, const Node &b) { return a.t < b.t; }
priority_queue<Node> q;

int main () {
	read(N), read(K);
    for(int i=1;i<=31;i++) {
		ll tmp = p[i];
		for(int j = 1; tmp <= N; ++j, tmp *= p[i]) 
            q.push((Node){tmp, p[i], j, i - 1}); 
    }
	while(K--) {
		Node now = q.top(); q.pop();
		if(!K) printf("%lld
", now.t);
		else if(now.y > 1)
			for(int i = 1; i <= now.z; ++i)
				q.push((Node){now.t / now.x * p[i], now.x, now.y - 1, i});
	}
    return 0;
}
原文地址:https://www.cnblogs.com/water-mi/p/10169483.html