wikioi 丑数

题目描述 Description

对于一给定的素数集合 S = {p1, p2, ..., pK},
来考虑那些质因数全部属于S 的数的集合。这个集合包括,p1, p1p2, p1p1, 和 p1p2p3 (还有其它)。这是个对于一个输入的S的丑数集合。
注意:我们不认为1 是一个丑数。
你的工作是对于输入的集合S去寻找集合中的第N个丑数。longint(signed 32-bit)对于程序是足够的。

第 1 行: 二个被空间分开的整数:K 和 N , 1<= K<=100 , 1<= N<=100,000.
第 2 行: K 个被空间分开的整数:集合S的元素

单独的一行,写上对于输入的S的第N个丑数。

4 19
2 3 5 7

27

 

题解

先把1入堆,每次将堆中最小的数弹出,并把其*s[i]都入堆。
我的代码有考虑到同一个数重复入堆的情况,所以有特判。而且我的代码要三百多毫秒,有些大神只要几十毫秒,如果各位大神们有更快的程序,希望能留给我作参考。谢谢!
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cmath>
using namespace std;
int n,m,zz=1,nn=1,count=0;
long long sh[102],d[10000005],ans[100002];
void swap(int a,int b)
{long long p=d[a]; d[a]=d[b]; d[b]=p;}
void wh(int w)
{
	int s;
	if((w<<1)<=nn&&d[w<<1]<d[w]) s=w<<1;
	else s=w;
	if(((w<<1)+1)<=nn&&d[(w<<1)+1]<d[s]) s=(w<<1)+1;
	if(s!=w)
	   {swap(w,s);
	    wh(s);
	   }
}
void insert()
{
	for(int i=1;i<=n;i++)
	   {d[++nn]=d[1]*sh[i];
	    int j=nn;
	    while(j>1&&d[j>>1]>d[j])
	       {swap(j>>1,j); j=j>>1;}
	   } 
	d[1]=d[nn]; nn--; wh(1);
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%lld",&sh[i]);
	d[1]=1;
	while(true)
	   {if(d[1]!=ans[zz-1])
	       {ans[zz]=d[1]; zz++;
	        if(zz==m+2) {printf("%lld\n",ans[zz-1]); break;}
	        insert();
		   } 
		else {d[1]=d[nn]; nn--; wh(1);}
		//if(ans[zz]!=ans[zz-1]) count++;
	   }
	//printf("%d %d\n",zz,nn); 
	//for(int i=1;i<=nn;i++) printf("%d ",ans[i]);
	/*int i=1,j=1;
	while(j<m)
	   {if(ans[i]!=ans[i]-1) j++;
	    i++;
	   }*/
	return 0;
} 


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值