题意是把$M$分成$a_1*a_2*a_3*a_4*\cdots*a_k(a_i\le a_{i+1})$的形式(指数都是$1$,意味着可能$a_i=a_j$)。

$a_1,a_2,a_3,\cdots,a_k,{a_k}^k\le N$,若存在$a_i\ne a_k$,它一定不是最大的。

因为把$a_1,a_2,a_3,\cdots,a_{k-1}$中不等于$a_k$的项替换成$a_k$,$M$变大了,但是${a_k}^k$没变,也就是依旧小于等于$N$。

因此含有$k$项的$M$,且末尾为$a_k$,只要求出这样最大的$M$,就可以枚举出剩下的其它项。

只需要确定末尾项$p_i\in\text{prime}$,以及$k$就可以枚举所有项了。

预处理$p_i<128$,之后开个大根堆不断弹值就可以了,弹$k$次即为所求。

关于正确性:由于堆中记录的值是代表了含有$k$项的$M$,且末尾为$a_k$中现存最大的一个,剩下的一定小于这个。

这样也是补充不漏的。

部分最大值的最大值即是当前全局最大值。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#define gc getchar()
#define ll long long
#define ld long double 
#define ull unsigned long long
using namespace std;
const int N=5e6+5,M=8555;
const int p[35]={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};
template<class o>
inline void qr(o &x)
{
    x=0;char c=gc;int f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
    while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
    x*=f;
}
template<class o>
void qw(o x)
{
    if(x<0)putchar('-'),x=-x;
    if(x/10)qw(x/10);
    putchar(x%10+48);
}
struct node
{
    ll s;int x,k,lst;
    node(ll s=0,int x=0,int k=0,int lst=0):s(s),x(x),k(k),lst(lst){}
    bool operator <(const node a)const{return s>a.s;}
};
struct Heap
{
    node a[N];int len;
    void up(int j){for(int i=j>>1;j>1&&a[j]<a[i];j=i,i=j>>1)swap(a[i],a[j]);}
    void down(int i)
    {
        for(int j=i<<1;j<=len;i=j,j=i<<1)
        {
            if(a[j+1]<a[j])++j;
            if(a[j]<a[i])swap(a[i],a[j]);
            else break;
        }
    }
    void push(node x){a[++len]=x;up(len);}
    void pop(){a[1]=a[len--];down(1);}
    node top(){return a[1];}
}q;
int main()
{
    ll n;int k;qr(n),qr(k);
    for(int i=1;i<=31;i++)
    {
        ll now=p[i];
        for(int j=1;now<=n;j++,now*=p[i])
            q.push(node(now,p[i],j,i-1));
    }
    while(k--)
    {
        node now=q.top();q.pop();
        if(!k)qw(now.s),puts("");
        else if(now.k>1)
        {
            for(int i=1;i<=now.lst;i++)
                q.push(node(now.s/now.x*p[i],now.x,now.k-1,i));
        }
    }
    return 0;
}