poj3307

可以证明,每个符合的数都由2,3,5,7相乘得到。

依据猜想:下一个出现的数是由前面某个数乘上这几个数之一得到的新的数。

  假设之前的数均满足序列,则因为下一个数必有2,3,5,7相乘得到,而这个数之前的数已经是2,3,5,7组成的最小数,则该数必为之前的数再乘上2,3,5,7得到。

  可由最小堆实现。

  后发现将其分为由之前的数分别乘上这四个数得到4个序列,可以证明序列递增,故只需记录其中每个序列位置即可。

因此得到算法。

#include<cstdio>
#define MAXN (1e18)
#define Maxn 80000  //个数比想象中少很多
long long n,ans[Maxn+1],p2,p3,p5,p7,f2[Maxn],f3[Maxn],f5[Maxn],f7[Maxn],all,a,b;
int main()
{
all=1;
ans[1]=1;
p2=p3=p5=p7=1;
for(int i=1;i<Maxn;i++){
f2[i]=ans[i]*2;
f3[i]=ans[i]*3;
f5[i]=ans[i]*5;
f7[i]=ans[i]*7;
a=(f2[p2]>f3[p3]?f3[p3]:f2[p2]);
b=(f5[p5]>f7[p7]?f7[p7]:f5[p5]);
ans[i+1]=a>b?b:a;
if(ans[i+1]==f2[p2]) ++p2;
if(ans[i+1]==f3[p3]) ++p3;
if(ans[i+1]==f5[p5]) ++p5;
if(ans[i+1]==f7[p7]) ++p7;
}
int t;
scanf("%d",&t);
while(t--){
scanf("%lld",&n);
printf("%lld
",ans[n]);
}
return 0;
}
原文地址:https://www.cnblogs.com/Mathics/p/3827059.html