简体   繁体   中英

Generating all divisors of a number given its prime factorization

I want to find all divisors of numbers in range [1,10 7 ] . I know it can be solved in O(sqrt(n)). But had to run sieve of Eratosthenes before this which can be easily modified to get prime factorization of a number(by keeping track of one of the prime factors of every number). So i wondering would it be more efficient to generate all the factor using its prime factorization?
Let n = p 1 k 1 * p 2 k 2 *....*p m k m

I think this notation can be obtained in O(m+Σk i ) after sieve.
I came up with following code to generate factors after a bit of thinking:

int factors[]={2,5};        // array containing all the factors
int exponents[]={2,2};      // array containing all the exponents of factors
                            // exponents[i] = exponent of factors[i]
vector <int> ans;           // vector to hold all possible factors

/*
*   stores all possible factors in vector 'ans'
*   using factors and exponents from index l to r(both inclusive)
*/
void gen(int factors[],int exponents[],vector<int>& ans,int l,int r)
{
    if(l==r)                        
    {
        int temp = 1;
        for(int i=0;i<=exponents[l];i++)
        {
            ans.push_back(temp);
            temp *= factors[l];
        }
        return;
    }
    gen(factors,exponents,ans,l+1,r);
    int temp=factors[l];
    int size = ans.size();
    for(int i=1;i<=exponents[l];i++)
    {
        for(int j=0;j<size;j++)
        {
            ans.push_back(ans[j]*temp);
        }
        temp *= factors[l];
    }
}

I think its Time complexity is at least Ω(no of factors) = Ω(∏(1+k i )).

So my question is:
1) Is it faster to generate factors this way than normally(O(sqrt(n)) loop method)?
2) Can the code given above be optimized?

The first most obvious optimization is to preallocate the answers vector. You know exactly how many factors there will be (since you already gave the formula as ∏(1+k i ) ).

If you manage the stack yourself instead of using recursion, you'll get the most optimal solution (each factor will require only 1 lookup and 1 multiplication).

Something like this?

int factors_count = 1;
for (int i = 0; i < r; ++i)
{
    factors_count *= 1+exponents[i];
}
ans.resize(factors_count);
ans[0] = 1;
int count = 1;
for (int stack_level = 0; stack_level < r; ++stack_level)
{
    const int count_so_far = count;
    const int prime = factors[stack_level];
    const int exponent = exponents[stack_level];
    int multiplier = 1;
    for (int j = 0; j < exponent; ++j)
    {
        multiplier *= prime;
        for (int i = 0; i < count_so_far; ++i)
        {
            ans[count++] = ans[i] * multiplier;
        }
    }
}

I haven't even tried compiling it, so caveat emptor.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM