Calculating phi(k) for 1<k<N

前端 未结 9 1840
花落未央
花落未央 2020-12-04 20:08

Given a large N, I need to iterate through all phi(k) such that 1 < k < N :

  • time-complexity must be O(N logN)
  • memory-complexity mus
9条回答
  •  旧巷少年郎
    2020-12-04 21:07

    The computation of phi(k) has to be done using the prime factorization of k, which is the only sensible way of doing it. If you need a refresher on that, wikipedia carries the formula.

    If you now have to compute all prime divisors of every number between 1 and a large N, you'll die of old age before seeing any result, so I'd go the other way around, i.e. build all numbers below N, using their possible prime factors, i.e. all primes less than or equal to N.

    Your problem is therefore going to be similar to computing all divisors of a number, only you do not know what is the maximum number of times you may find a certain prime in the factorization beforehand. Tweaking an iterator originally written by Tim Peters on the python list (something I've blogged about...) to include the totient function, a possible implementation in python that yields k, phi(k) pairs could be as follows:

    def composites(factors, N) :
        """
        Generates all number-totient pairs below N, unordered, from the prime factors.
        """
        ps = sorted(set(factors))
        omega = len(ps)
    
        def rec_gen(n = 0) :
            if n == omega :
                yield (1,1)
            else :
                pows = [(1,1)]
                val = ps[n]
                while val <= N :
                    pows += [(val, val - pows[-1][0])]
                    val *= ps[n]
                for q, phi_q in rec_gen(n + 1) :
                    for p, phi_p in pows :
                        if p * q > N :
                            break
                        else :
                            yield p * q, phi_p * phi_q
    
        for p in rec_gen() :
            yield p
    

    If you need help on computing all prime factors below N, I've also blogged about it... Keep in mind, though that computing all primes below 1012 is in itself quite a remarkable feat...

提交回复
热议问题