Find a number that is not an ugly number from 1 to 10,000,000

I had some kind of problem when we tried to figure out not an ugly number. Ugly numbers are numbers whose only major factors are 2, 3, or 5. So what is this number not ugly? I'm trying to figure out non-ugly numbers between 1 and 100,000,000. My program can solve the problem, but it seems a bit slow. How can I do it faster? Here is the code:

#include <iostream>
#include <queue>
using namespace std;
typedef pair<unsigned long,int> node_type;
main()
{
    //generates 1500 ugly numbers into result[];
    unsigned long result[1500];
    priority_queue<node_type,vector<node_type>,greater<node_type> > Q;
    Q.push(node_type(1,2));
    for(int i=0;i<1500;i++)
    {
        node_type node = Q.top();
        Q.pop();
    switch(node.second)
    {
        case 2:Q.push(make_pair(node.first*2,2));
        case 3:Q.push(make_pair(node.first*3,3));
        case 5:Q.push(make_pair(node.first*5,5)); 
    }
    result[i]=node.first;
}
/*****************************************************
//Here is the approach I used:
//The initial value of the integer k is 1;
//and will increase by 1 every time 
//k will be checked if it a ugly number,if not increase by 1,keep doing
//this till k is not a ugly number,then count how much ugly number(we may 
//call it n) is less the the
//current value of k.The result of (k-n) is the order number of this (k)ใ€€not ugly
//for example:the 1st not ugly number is 7.
// there are 6 ugly number less than 7,which are 1 2 3 4 5 6,
// k=1-->k==2-->.....k=7, k-n=7-6=1,so 7 is the 1st not ugly number
***************************************************************/
int T;  // The amount of cases
cin>>T;
while(T--)
{
    int n;
    int k=0,i=0,count=0;
    cin>>n;

    while(n)
    {
        if((k+1)==result[i]) {k++;i++;count++;}
        else 
        {
            k++;
            if(k-count==n) {cout<<k<<endl;break;}
        }
    }
}}

The big problem is that it doesn't seem fast enough! Can you tell me how to do it faster? Or is there another method to solve the problem?

+4
source share
3 answers

, . , , , . Brute-force- 100

#include <iostream>

bool is_ugly(unsigned n) {
  while(n % 5 == 0) n /= 5;
  while(n % 3 == 0) n /= 3;
  while(n % 2 == 0) n /= 2;

  return n == 1;
}

int main() {
  unsigned counter = 0;
  for(unsigned i = 1; i <= 100000000; ++i) {
    if(!is_ugly(i)) {
      ++counter;
    }
  }

  std::cout << counter << std::endl;
}

1 . , , 99998895 100000000, . /dev/null ( ), 6 (~ 10 , ), libstd++ gcc 4.9 -O2. , , , .

, , , ( , , ), . - , . :

#include <iostream>
#include <set>      // could also use an unordered_set, except that it turns
                    // out to be a pessimization

void generate_uglies(unsigned n, std::set<unsigned> &num, unsigned threshold) {
  // Abort recursion if we break the upper limit or find a number
  // that was already tested
  if(n <= threshold && num.find(n) == num.end()) {
    // Remember this ugly number
    num.insert(n);

    // Since n is an ugly number, these three are also ugly numbers.
    generate_uglies(n * 2, num, threshold);
    generate_uglies(n * 3, num, threshold);
    generate_uglies(n * 5, num, threshold);
  }
}

int main() {
  std::set<unsigned> num;

  generate_uglies(1, num, 100000000);

  std::cout << num.size() << std::endl;
}

, ...

$ time ./a.out 
1105

real    0m0.001s
user    0m0.000s
sys     0m0.000s

, num.find(n) == num.end() - -, is_ugly(n) ( is_ugly ), std::unordered_set 2-3 .

. , - std::vector<bool> 100 :

// num is to have the wanted size in advance and be full of false
void generate_uglies(unsigned n, std::vector<bool> &num) {
  if(n < num.size() && !num[n]) {
    num[n] = true;
    generate_uglies(n * 2, num);
    generate_uglies(n * 3, num);
    generate_uglies(n * 5, num);
  }
}

!num[i] . !num[i] , is_ugly ( 100 5 ) 1. , , , . , 12,5 .

1 , . 1,5- i7.

+5

, , , n- .

n- - O (N), , , O (log (N)).

T , T , .

, .

#include <iostream>
#include <queue>
using namespace std;
typedef pair<unsigned long,int> node_type;
int main()
{
    //generates 1500 ugly numbers into result[];
    unsigned long result[1500];
    priority_queue<node_type,vector<node_type>,greater<node_type> > Q;
    Q.push(node_type(1,2));
    for(int i=0;i<1500;i++)
    {
        node_type node = Q.top();
        Q.pop();
        switch(node.second)
        {
            case 2:Q.push(make_pair(node.first*2,2));
            case 3:Q.push(make_pair(node.first*3,3));
            case 5:Q.push(make_pair(node.first*5,5));
        }
        result[i]=node.first;
    }

    int T;  // The amount of cases
    cin>>T;
    //b_search_data[i] mean the count of non ugly number blow or equal i, i start from 1
    unsigned long b_search_data[1501];

    for (int i=0; i<1500; i++)
    {
        b_search_data[i] = result[i] - i - 1;
    }
    vector<int> search_data(b_search_data, b_search_data+1500);
    while(T--)
    {
        int n;
        int k=0,i=0,count=0;
        cin>>n;
        // use binary search here to find the n-th non ugly number instead your approach
        int position = upper_bound(search_data.begin(), search_data.end(), n-1) - search_data.begin();
        // position means
        cout<<position + n<<endl;
    }
}
+1

.

, N , 2*N, 3*N 5*N .

, 2*N, 3*N 5*N N, , MAX , N, , 2*N, 3*N 5*N ( ).

, uglies, , , , 6 3*2, ( ), 2*3 ( --- )

, , :

#include <cstdio>
#include <set>

using namespace std;

const unsigned N = 10000000;

set<unsigned> uglys;
unsigned n_collis = 0;


void srch_ugly(unsigned n)
{
    if (uglys.find(n) != uglys.end()) { /* found in set */
        ++n_collis;
    } else {
        uglys.insert(n);
        if (2*n < N) srch_ugly(2*n);
        if (3*n < N) srch_ugly(3*n);
        if (5*n < N) srch_ugly(5*n);
    } /* if */
} /* srch_ugly(unsigned) */

int main()
{
    unsigned col = 0; /* printing column */

    srch_ugly(1);

    /* print results */    
    printf("%lu uglys.  %u collissions.\n", uglys.size(), n_collis);
    for (set<unsigned>::iterator i = uglys.begin();
            i != uglys.end();
            ++i)
    {
        if (col >= 72) {
            puts("");
            col = 0;
        } /* if */
        col += printf("%s%i", col ? " " : "", *i);
    } /* for */
    if (col) puts("");
} /* main */

printf stdio, 72 , printf ( , ostream), .

0

All Articles