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\n",ans[n]); } return 0; }
那么多的束缚,我不曾放弃过;那么多的险阻,我不曾倒下过。