USACO Training "Humble Numbers"
USACO Training "Humble Numbers"
Problem Statement
In this problem we are asked to find the n-th "humble number" of a set of primes of length K <= 100.A humble number of a set is defined as a number whose prime factors are as subset of the set.
We are asked to find the n-th humble number of a set, when considered from lowest to greatest.
Notices
- Possibly most importantly, we notice that any humble number of a set can be created by multiplying elements of the set together.
- Clearly a recursive search (i.e. recursively multiplying elements by other elements) will take both too long (O(n^n)) and use too much memory (O(n!)). We try a DP approach.
DP Approach
We calculate the humble numbers in order (i.e. from the first to the Nth). For simplicity (and correctness), we assume that 1 is the 0th humble number.Once we have the first X humble numbers, we compute the X+1-th humble number as follows:
- Set best=0x7FFFFFFF (largest signed long int) and bestPrime=-1
- For each prime P:
- find the smallest previous humble number H such that H*P is greater than the last (Xth) humble number;
- if this is smaller than best set best to this new value and set bestPrime to P;
- go back to step 2 until all primes are done
- set the X+1th humble number to be best
Optimizations
A rather glaring optimization is that H*P for the same P will always increase as X increases. So, we can set a "start value" for each prime in an array so we won't re-check unnecessarily previous H values that were deemed too small.The second is that the humble number array will always be sorted, so we can use <algorithm>'s std::upper_bound. But we need to find the humble number H such that H*P is greater than the Xth humble number, not directly comparing H! We think of comparing H with (Xth)/P, but std::upper_bound automatically casts double values to const int& values. Therefore, we use <functional>'s std::less<> - then, std::upper_bound does not need to (and will not) can (Xth)/P to a int.
Comments
Post a Comment