对于每个质数求出其作为最大质因子时最多能有几个质因子,开始时将这些ak1~akmaxk扔进堆。考虑构造方案,使得每次取出最大值后,最大质因子、质因子数均与其相同且恰好比它小的数都在堆里。类似暴搜,对于当前考虑的质因子,可以将其去掉并乘上一个恰好比它小的小的质因子,也可以转而考虑下一个质因子。于是给堆中元素记录当前考虑的质因子、最小质因子,每次进行两种更新即可。
正解似乎是可持久化可并堆+dp,当然不会。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> using namespace std; #define ll long long #define N 800010 int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} ll n;int k; int prime[130],cnt; bool flag[130]; struct data { ll x;int i,j,k; bool operator <(const data&a) const { return x<a.x; } }; priority_queue<data> q; int main() { #ifndef ONLINE_JUDGE freopen("bzoj4524.in","r",stdin); freopen("bzoj4524.out","w",stdout); const char LL[]="%I64d "; #else const char LL[]="%lld "; #endif cin>>n>>k; for (int i=2;i<128;i++) for (int j=2;i*j<128;j++) flag[i*j]=1; for (int i=2;i<128;i++) if (!flag[i]) prime[++cnt]=i; for (int i=1;i<=cnt&&prime[i]<=n;i++) { ll x=1; for (int j=1;n/prime[i]>=x;j++) { x*=prime[i]; q.push((data){x,i,i,i}); } } k--; while (k--) { data x=q.top();q.pop(); if (x.j>1&&(x.j<x.i||x.x%(prime[x.i]*prime[x.i])==0)) { ll t=x.x/prime[x.j]*prime[x.j-1]; if (t%prime[x.j]==0) q.push((data){t,x.i,x.j,x.j-1}); else q.push((data){t,x.i,x.j-1,x.j-1}); } if (x.k>1&&x.k<x.j) { ll t=x.x/prime[x.k]*prime[x.k-1]; if (t%prime[x.k]==0) q.push((data){t,x.i,x.k,x.k-1}); else q.push((data){t,x.i,x.k-1,x.k-1}); } } cout<<q.top().x; return 0; }