problem 1095

         A number whose only prime factors are 2,3,5 or 7 is called a humble number. The sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25, 27, ... shows the first 20 humble numbers.

Write a program to find and print the nth element in this sequence. (1 <= n <= 5842)

   容易想到用一个按照自然顺序递增的循环一个一个去判断是否满足2a1 * 3a2 * 5a3 * 7a4,并且将满足的数依次放入数组中直至第n个时结束输出。但是由于当n = 5842时结果为20亿(也就是说要循环20亿次!),time limited Exceeded!不可行。

   重新考虑后给出如下解答:

   将结果放入数组r中,在假设已求得前n-1个f的情况下第n个应该有这样的形式:

   r[n] = min{2 * r[i1],3 * r[i2],5 * r[i3],7 * r[i4]},其中i1,i2,i3,i4待定且均小于等于n-1。

   接下来需要确定i1,i2,i3,i4,容易得出唯一确定的条件:

   r[i-1] <= r[n-1]/b < r[i],    (b,i) = { (2.0,i1), (3.0,i2), (5.0,i3), (7.0,i4) },    (这里要注意了,不是b*r[i-1] <= r[n-1] < b*r[i]  因为b*r[i]会超过43亿溢出)

   再由r中的结果是按升序排列的,即可以用二分法查找出满足的i1,i2,i3,i4。

   还可以做一个小小的改进,当求出r[n]后保留此时的i1,i2,i3,i4,因为决定r[n+1]的i1,i2,i3,i4一定比决定r[n]的要大,这样可以减少查找的次数。

Accepted1095c00:00.02420K

 

 

#include<stdio.h>
#define min2(a,b) ((a)<(b)?(a):(b))
#define min4(a,b,c,d) min2(min2(a,b),min2(c,d))
int n,t=20 ;
int
 i1,i2,i3,i4;
long r[5843= {0,1234567891012141516182021242527
};
void output(int
 k)
{
        
if(n%100>=10 && n%100<=20
)
        {
                printf(
"The %dth humble number is %ld."
,n,r[n]);
                
return
;
        }
        
switch
( k )
        {
        
case 1
:
                printf(
"The %dst humble number is %ld."
,n,r[n]);
                
break
;
        
case 2
:
                printf(
"The %dnd humble number is %ld."
,n,r[n]);
                
break
;
        
case 3
:
                printf(
"The %drd humble number is %ld."
,n,r[n]);
                
break
;
        
default
:
                printf(
"The %dth humble number is %ld."
,n,r[n]);
                
break
;
        }
}
int search(int s,int e,int n,double
 b)
{
        
int i=
e;
        
double temp = r[n]/
b;
        
while(!(((double)r[i-1<= temp) && (temp < (double
)r[i])))
        {
                i 
= (e+s)/2
;
                
if((double)r[i] <=
 temp)
                        s 
=
 i;
                
else

                        e 
=  i;               
        }
        
return
 i;
}
void
 solve()
{
        
if(n>
t)
        {
                
int m = t+1
;
                
while(m <=
 n)
                {
                        i1 
= search(i1,m-1,m-1,2
);
                        i2 
= search(i2,m-1,m-1,3
); 
                        i3 
= search(i3,m-1,m-1,5
); 
                        i4 
= search(i4,m-1,m-1,7
); 
                        r[m
++= min4(2*r[i1],3*r[i2],5*r[i3],7*
r[i4]);
                        t
++
;
                }
        }
        output(n
%10
);
}
void
 main()
{
        i1 
= i2 = i3 = i4 = 1
;
        
while((scanf("%d",&n)!=EOF) && (n!=0
))              
        {
                solve();
                putchar(
10
);
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值