[usaco3.1.3]humble

 这道题想了很久想不到,只好看题解(在下服气),题解是666的,不用多说上代码。

  第一个是官方题解:记录下到第i-1个丑数时,每一个素数枚举到哪一个丑数,然后直接从那个丑数继续开始枚举。

  第二个是手写堆+set判重,每一次取出最小的数作为第i个丑数,然后枚举每一个素数扩展新元素加入堆,再用set判重。(但剪枝写的没有证明)

/*
ID:abc31261
LANG:C++
TASK:humble 
*/
#include<cstdio>
#include<cstring>
#include<map>
#include<iostream>
using namespace std;
const int maxn=200,maxm=700000;
long long num[maxn],hash[maxm+1],f[maxn],len,hum[maxm];     //f数组就是记录枚举到哪一个。

void add(int x)
{
     int i=x%maxm,j=i+1;
     if (hash[i]==0)hash[i]=x;
        else 
        {
             while (j!=i && hash[j]!=0)j=(j+1)%maxm;
             hash[j]=x;
        }
}

int check(int x)
{   
    int i=x%maxm,j=i+1;
    if (hash[i]==x)return 1;
       else 
       {
            while (j!=i && hash[j]!=x && hash[j]!=0)j=(j+1)%maxm;
            if (hash[j]==x)return 1;
       }
    return 0;
}
int main()
{
    int i,j,k,n,l,p,q;
    freopen("humble.in","r",stdin);
    freopen("humble.out","w",stdout);
    scanf("%d%d",&k,&n);
    memset(hash,0,sizeof(hash));
    memset(f,0,sizeof(f));
    for (i=1;i<=k;i++)scanf("%d",&num[i]);
    hum[1]=len=1;                                                //为了方便,把1也看作一个丑数。
    for (i=1;i<=n;i++)
    {
        int l=0;
        for (j=1;j<=k;j++)
        {
            while (check(num[j]*hum[f[j]+1])==1)f[j]++;
            if ((num[j]*hum[f[j]+1]<num[l]*hum[f[l]+1])|| l==0)l=j; //枚举
        }
        hum[++len]=num[l]*hum[++f[l]];
        add(hum[len]);
    }
    cout<<hum[len]<<endl;
    return 0;
}

 

 

/*
ID:abc31261
LANG:C++
TASK:humble 
*/
#include<cstdio>
#include<cstring>
#include<set>
#include<iostream>
using namespace std;
const int maxn=200,maxm=100000;
set<long long> s;
long long heap[maxm*4],len=0;
int k,n,num[maxn];

long long get()
{
    long long i=1,x=heap[1];
    swap(heap[1],heap[len--]);
    while (i*2<=len)
    {
          int j=i*2;
          if (i*2+1<=len && heap[i*2+1]<heap[i*2])j=i*2+1;
          if (heap[i]>heap[j])
          {
             swap(heap[i],heap[j]);
             i=j;
          }
          else break;
    }
    return x;
}

void put(long long x)
{
     long long i=++len,j;
     heap[len]=x;
     while (i>1)
     {
           if (heap[i/2]>heap[i])
           {
              swap(heap[i/2],heap[i]);
              i=i/2;
           }
           else break;
     }
     if (len>n)len=n;              //这个直接剪的话没有证明(汗)。
}
int main()
{
    int i,j;
    long long x;
    freopen("humble.in","r",stdin);
    freopen("humble.out","w",stdout);
    memset(heap,0,sizeof(heap));
    cin>>k>>n;
    for (i=1;i<=k;i++)scanf("%d",&num[i]);
    put(1);                  //把1看作一个丑数
    for (i=1;i<=n;i++)
    {
        x=get();
        for (j=1;j<=k;j++)
            if (s.count(num[j]*x)==0)
            {
               put(num[j]*x);
               s.insert(num[j]*x);
            }
    }
    cout<<get()<<endl;
    return 0;
}

 

posted @ 2015-12-05 15:10  Sun_Sea  阅读(164)  评论(0编辑  收藏  举报