POJ 2247 && HDU 1058 Humble Numbers(数论)

Description
定义一种集合,使得其中的元素的素数因子只能是2,3,5 ,7
即:11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25, 27, …
要求这个集合的第n个数是多少
Input
多组输入,每组用例一个整数n表示查询该集合第n个元素,以n=0结束输入
Output
对于每组用例,输出集合第n个元素
Sample Input
1
2
3
4
11
12
13
21
22
23
100
1000
5842
0
Sample Output
The 1st humble number is 1.
The 2nd humble number is 2.
The 3rd humble number is 3.
The 4th humble number is 4.
The 11th humble number is 12.
The 12th humble number is 14.
The 13th humble number is 15.
The 21st humble number is 28.
The 22nd humble number is 30.
The 23rd humble number is 32.
The 100th humble number is 450.
The 1000th humble number is 385875.
The 5842nd humble number is 2000000000.
Solution
这个集合是通过集合里的每一个数 ×2,×3,×5,×7来扩展的,要想从小到大,从ugly[1]开始扩展时,由于×2,×3,×5,×7大小不同,所以ugly[]的下一个元素是这四个数的最小值。所以到下次时,2是在乘以新的元素,而3,5,7还在乘原来的元素,但这四个数比较后最小的继续添加进集合里。由于有了这样的延迟作用,我们可以设置四个指针u2,u3,u5,u7分别指向2,3,5,7待乘的数。
要记得处理重复的数,在每扩展一个元素时,判断该数是否能通过其他数来乘得,是的话就右移p
Code

#include<stdio.h>
#define min(x,y) x<y?x:y
int main()
{
    int i,u2,u3,u5,u7,n;
    long int ugly[6000];
    ugly[1]=1;
    u2=1;
    u3=1;
    u5=1;
    u7=1;
    for(i=2;i<6000;i++)
    {
        ugly[i]=min(ugly[u3]*3,ugly[u5]*5);
        ugly[i]=min(ugly[i],ugly[u2]*2);
        ugly[i]=min(ugly[i],ugly[u7]*7);
        if(ugly[i]==ugly[u2]*2)
            u2++;
        if(ugly[i]==ugly[u3]*3)
            u3++;
        if(ugly[i]==ugly[u5]*5)
            u5++;
        if(ugly[i]==ugly[u7]*7)
            u7++;
    }
    while(scanf("%d",&n)&&n)
    {
        if(n%100>10&&n%100<20)
            printf("The %dth humble number is %d.\n",n,ugly[n]);
        else if(n%10==1)
            printf("The %dst humble number is %d.\n",n,ugly[n]);
        else if(n%10==2)
            printf("The %dnd humble number is %d.\n",n,ugly[n]);
        else if(n%10==3)
            printf("The %drd humble number is %d.\n",n,ugly[n]);
        else
            printf("The %dth humble number is %d.\n",n,ugly[n]);
    }
}

你可能感兴趣的:(POJ 2247 && HDU 1058 Humble Numbers(数论))