回 帖 发 新 帖 刷新版面

主题:请教一道题比较好的算法

题目在:http://acm.pku.edu.cn/JudgeOnline/problem?id=1338
我是这样做的,但超时了,能提供一个比较好的算法马?
#include<iostream>
using namespace std;
const int N=1500;
int main()
{
    int a[N],i=-1,j,k,m,n,max,b[3]={2,3,5},c[N];
    do
    {
        i++;
        cin>>a[i];
    }while(a[i]);
    max=a[0];
    for(j=0;j<i;j++)
    {
        if(max<=a[j])
            max=a[j];
    }
    c[0]=1;
    k=1;
    n=1;
    while(k<max)
    {
        n++;
        m=n;
        while(m>1)
        {
            for(j=0;j<3;j++)
            {
                if(m%b[j]==0)
                {
                    m=m/b[j];
                    j=-1;
                }
            }
            if(j<3&&m>1)
                continue;
            if(j>=3&&m>1)
            {
                break;
            }
           if(m==1)
           {
              c[k]=n;
              k++;
              break;
           }
        }
    }
    for(j=0;j<i;j++)
        cout<<c[a[j]-1]<<endl;
    return 0;
}

回复列表 (共5个回复)

沙发

思路:一个Ugly Number只能由某个小一点的Ugly Number*2,*3,*5得到。

板凳

#include<stdio.h>
#include<stdlib.h>
#define MAX 800

int main(void)
{
    unsigned long lib[MAX] = {1,};
    unsigned long n, num;
    int k = 1;
    
    for (n=2; k<MAX; n++)
    {
        num = n;
        while (num % 2 == 0)
            num /= 2;
        while (num % 3 == 0)
            num /= 3;
        while (num % 5 == 0)
            num /= 5;
        
        if (num == 1)
            lib[k++] = n;    
    }
    
//    int j;
//    for (j=0; j<k; j++)
//        printf("%ld\t", lib[j]);
    
    unsigned int data[MAX] = {0};
    int temp;
    scanf("%d", &temp);
    
    int len = 0;
    while (temp != 0)
    {
        data[len++] = temp;
        scanf("%d", &temp);
    }
    
    int i;
    for (i=0; i<len; i++)
        printf("%d\n", lib[data[i]-1]);
    
      system("pause");     
       return 0;
}   

3 楼

/*
算法分析:观察数列:
2 3 5
4 6 9 10 15 25
8 12 18 27 20 30 45 50 75 125
16 24 36 54 81 40 60 90 135 100 150 225 250 375 625
32 48 72 108 162 243 80 120 180。。。 
可以看出每行依次递增3,4, 5,6。。。个元素。以第2行为例,递增的元素分别是
4 = 2 * 2, 6 = 3 * 2, 9 = 3 * 3,后面三个元素10,15,25分别由2,3,5各乘以5得到;    
以第3行为例,递增的元素分别是
8 = 4 * 2, 12 = 6 * 2, 18 = 9 * 2,27 = 9 * 3;
后面三个元素20 30 45 50 75 125分别由4 6 9 10 15 25各乘以5得到;
由此可以得出规律:
设k表示栈顶,由于数组栈已经存储了4个元素{1,2,3,5,},则k初始值为4。
设第n(n>1)行最左边元素的下标为left,最右边元素的下标为right-1,sum表示第n行的元素个数,
其中n初始值为2,sum初始值为1。则对于第n行(n>1)来说,
 sum += n; left = k - sum; right = k;
 根据第n行的元素值,求出第n+1行的各个元素。
 其中前n-1个元素为  for (i=left; i<left+n; i++)
                lib[k++] = lib[i] * 2;
 第n个元素为 lib[k++] = lib[left+n-1] * 3;
 后面的sum个元素为 for (; left<right; left++)    
                lib[k++] = lib[left] * 5;
依此类推,直到存储了足够的元素。
注意:此处不能以k==MAX为结束标志,因为数组的元素不是递增排列的,有可能遗漏前面较小的元素。
解决方案是不接受较大的数(设其值为0),以便能全部求出前面较小的数。
最后对得到的数组进行排序,消去前面为0的元素。
一点疑惑:结果似乎有问题,但尚未找到原因     
*/
#include<stdio.h>
#include<stdlib.h>
#define MAX 1500

int Move(unsigned long lib[], int len);

static int Compare(const void *p1, const void *p2)
{
    return (*(unsigned long *)p1) - (*(unsigned long *)p2);
}

int main(void)
{
    unsigned long lib[MAX*10] = {1,2,3,5,};
    int left, right;
    int k = 4;
    int n = 2;
    int sum = 1;
            
    while (k < MAX)
    {
        sum += n;
        left = k - sum;
        right = k;
        
        int i;
        for (i=left; i<left+n; i++)
        {
            if (lib[i] * 2 < 2119458569)    //若数值太大(溢出),则取0 
                lib[k++] = lib[i] * 2;
            else
                lib[k++] = 0;
        }
        if (lib[left+n-1] * 3 < 2119458569)    //若数值太大(溢出),则取0 
            lib[k++] = lib[left+n-1] * 3;
        else
            lib[k++] = 0;
            
        for (; left<right; left++)    //若数值太大(溢出),则取0 
        {
            if (lib[left] * 5 < 2119458569)    
                lib[k++] = lib[left] * 5;
            else
                lib[k++] = 0;
        }                 
        n++;
    }
//    printf("\nk = %d\n", k);
    qsort(lib, k, sizeof(unsigned long), Compare);//非递增排列
    
    k = Move(lib, k); //去掉数值为0的元素 
//    printf("\nk = %d\n", k);
    //int j;    
//    for (j=0; j<k; j++)
//        printf("%ld\t", lib[j]);
    
    unsigned int data[MAX] = {0};
    int temp;
    scanf("%d", &temp);
    
    int len = 0;
    while (temp != 0)
    {
        data[len++] = temp;
        scanf("%d", &temp);
    }
    
    int i;
    for (i=0; i<len; i++)
        printf("%d\n", lib[data[i]-1]);
        
      system("pause");     
       return 0;
}   

int Move(unsigned long lib[], int len)
{
    int i = 0;
    while (lib[i] == 0)
        i++;
    
    int j = 0;
    while (i < len)
        lib[j++] = lib[i++];
        
    return j;
}

4 楼

一点疑惑:结果似乎有问题,但尚未找到原因----找到了,原来是k的上限设置太小了,增大上限后就正确了.
修改的代码如下:unsigned long max = MAX*2;        
    while (k < max)

5 楼

我不懂英文能把这道题贴出来吗

我来回复

您尚未登录,请登录后再回复。点此登录或注册