[成绩]
[报告]
佳哥的课件里有这道题,看到了顺便就切掉了。
首先,忽略6503581(那个和6503693一个算法,就是它没开LONG LONG,就WA了)。
这里有两个算法:6503693是O(NlogN)的;6504064是O(N)的;还有个O(1)的,我没写。
O(NlogN):就是佳哥课件里的那个算法。维护一个优先队列(二叉堆),每当从队首取出一个元素,都将它的2,3,5倍数加入队列。反复此过程,当取出N个数时,最后取出的数为最后的答案。
O(N):这个是lordxfastx告诉我的一个算法。由于O(NlogN)中每取出的数*2,都必然比它前面取出的数*2小(3,5同理)。因此,可以维护3个单调队列,分别保存*2,*3,*5的值。每次取出的数为三个单调队列中队首的最小值。由于这个算法不需要多余的交换什么的,所以就是O(N)的。
O(1):显然——打表……(不解释)
[程序]
6503693:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define func(x) inline static x
#define N 9973
using namespace std;
long long h[N+1];
long long a[N+1],n;
func(void) down(long x)
{
long long i=x,j=x<<1,ax=a[x];
while (j<=n)
{
if (j<n&&a[j]>a[j+1]) j++;
if (ax>a[j])
{
a[i]=a[j];
i=j;j=i<<1;
}else break;
}
a[i]=ax;
}
func(void) up(long x)
{
long long i=x,j=x>>1,ax=a[x];
while (j>0&&ax<a[j])
{
a[i]=a[j];
i=j;j=i>>1;
}
// if (a[j]!=ax)
a[i]=ax;
// else
// {
// a[i]=a[n--];
// down(i);
//}
}
long m=0;
func(bool) hash(long long x)
{
long ax=x%N;
while (h[ax]!=0&&h[ax]!=x) ax=(ax+1)%N;
if (h[ax]==x) return true;
else return !(h[ax]=x);
}
func(void) insert(long long x)
{
if (hash(x)) return;
m++;
a[++n]=x;
up(n);
}
func(void) erase()
{
a[1]=a[n--];
down(1);
}
func(void) print()
{
printf("%d:",n);
for (long i=1;i<=n;i++)
printf("%d ",a[i]);
printf("\n");
}
func(long long) solve(long k)
{
memset(h,0,sizeof(h));
memset(a,0,sizeof(a));
m=0;
n=1;
a[1]=1;
long long ax;
while (k>1)
{
ax=a[1];
k--;
erase();
insert(ax*2);
insert(ax*3);
insert(ax*5);
// print();
}
//cout << m << endl;
Run ID | User | Problem | Result | Memory | Time | Language | Code Length | Submit Time |
6504064 | weweweer9 | 1338 | Accepted | 992K | 0MS | G++ | 2148B | 2010-03-02 19:40:21 |
6503693 | weweweer9 | 1338 | Accepted | 824K | 0MS | G++ | 1772B | 2010-03-02 18:36:01 |
6503581 | weweweer9 | 1338 | Wrong Answer | G++ | 1427B | 2010-03-02 18:19:23 |
佳哥的课件里有这道题,看到了顺便就切掉了。
首先,忽略6503581(那个和6503693一个算法,就是它没开LONG LONG,就WA了)。
这里有两个算法:6503693是O(NlogN)的;6504064是O(N)的;还有个O(1)的,我没写。
O(NlogN):就是佳哥课件里的那个算法。维护一个优先队列(二叉堆),每当从队首取出一个元素,都将它的2,3,5倍数加入队列。反复此过程,当取出N个数时,最后取出的数为最后的答案。
O(N):这个是lordxfastx告诉我的一个算法。由于O(NlogN)中每取出的数*2,都必然比它前面取出的数*2小(3,5同理)。因此,可以维护3个单调队列,分别保存*2,*3,*5的值。每次取出的数为三个单调队列中队首的最小值。由于这个算法不需要多余的交换什么的,所以就是O(N)的。
O(1):显然——打表……(不解释)
[程序]
6503693:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#define func(x) inline static x
#define N 9973
using namespace std;
long long h[N+1];
long long a[N+1],n;
func(void) down(long x)
{
long long i=x,j=x<<1,ax=a[x];
while (j<=n)
{
if (j<n&&a[j]>a[j+1]) j++;
if (ax>a[j])
{
a[i]=a[j];
i=j;j=i<<1;
}else break;
}
a[i]=ax;
}
func(void) up(long x)
{
long long i=x,j=x>>1,ax=a[x];
while (j>0&&ax<a[j])
{
a[i]=a[j];
i=j;j=i>>1;
}
// if (a[j]!=ax)
a[i]=ax;
// else
// {
// a[i]=a[n--];
// down(i);
//}
}
long m=0;
func(bool) hash(long long x)
{
long ax=x%N;
while (h[ax]!=0&&h[ax]!=x) ax=(ax+1)%N;
if (h[ax]==x) return true;
else return !(h[ax]=x);
}
func(void) insert(long long x)
{
if (hash(x)) return;
m++;
a[++n]=x;
up(n);
}
func(void) erase()
{
a[1]=a[n--];
down(1);
}
func(void) print()
{
printf("%d:",n);
for (long i=1;i<=n;i++)
printf("%d ",a[i]);
printf("\n");
}
func(long long) solve(long k)
{
memset(h,0,sizeof(h));
memset(a,0,sizeof(a));
m=0;
n=1;
a[1]=1;
long long ax;
while (k>1)
{
ax=a[1];
k--;
erase();
insert(ax*2);
insert(ax*3);
insert(ax*5);
// print();
}
//cout << m << endl;