BZOJ4524 CQOI2016伪光滑数(堆)

  对于每个质数求出其作为最大质因子时最多能有几个质因子,开始时将这些ak1~akmaxk扔进堆。考虑构造方案,使得每次取出最大值后,最大质因子、质因子数均与其相同且恰好比它小的数都在堆里。类似暴搜,对于当前考虑的质因子,可以将其去掉并乘上一个恰好比它小的小的质因子,也可以转而考虑下一个质因子。于是给堆中元素记录当前考虑的质因子、最小质因子,每次进行两种更新即可。

  正解似乎是可持久化可并堆+dp,当然不会。

#include 
#include
#include
#include
#include
#include
#include
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 q;
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj4524.in","r",stdin);
    freopen("bzoj4524.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#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.j0))
        {
            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;
}

 

转载于:https://www.cnblogs.com/Gloid/p/9889439.html

你可能感兴趣的:(BZOJ4524 CQOI2016伪光滑数(堆))