-2

Let there be integer n.

Count how many numbers there are from 1 to n that has the sum of divisors being a prime number.

Example:

Input: 10

Output: 3

Explanation: There are 3 numbers with the sum of divisors being a prime: 2,4,9.

2: 1,2: Sum = 1+2 = 3.

4: 1,2,4: Sum = 1+2+4 = 7

9: 1,3,9: Sum = 1+3+9 = 13

I took this problem from a Vietnamese contest. At first I tried to solve it using a function to calculate divisors and the Sieve of Eratosthenes, but it can only run in O(n log n), which isn't plausible for n = 10^9. Does anyone have any idea what's the best solution to count how many numbers there are with the sum of divisors being a prime number?

Edit: It's from a piece of paper, there's no source of this unfortunately. If there were, I would've done so without asking.

4
  • 1
    Does anyone have any idea what's the best solution to count how many numbers there are with the sum of divisors being a prime number? Yes. Go to the forums for the Vietnamese contest, and ask this question there. Commented Feb 9 at 14:53
  • 1
    This is a problem to apply some analytical skills. Just make a table with hundred of divisor sums and look at this table. Notice, WHAT results are primes. Check hypothesis for thousands. Count appropriate numbers. To help Commented Feb 9 at 15:27
  • The sieve is a great way to generate a list of primes, but a horrible way to test the primality of a single number. But I think the real problem here is factorizing the numbers which gets increasingly hard as the numbers get large. Commented Feb 9 at 16:00
  • 2
    Your question would be better if you shared the code you've already tried, and explained better why it's not sufficient. Commented Feb 9 at 19:07

3 Answers 3

4

Besides 2, only even-exponent prime-powers can have the desired property.

Quick start: the sum of divisors of a number with prime factors pi and their exponents αi is

formula

and we want this product to be prime (image from MathWorld). So we can't have more than one prime factor.

Let's say we're looking at the number x·72 with x not divisible by 7. Then the divisors are the divisors of x, and the same divisors each multiplied by 7, and the same divisors multiplied by 49. Their sum is thus 1+7+49 times the sum of the divisors of x. If the latter is larger than 1, that's not prime.

So you can't combine prime factor 7 with any other. And likewise you can't combine any different prime factors. We only need to consider prime powers.

Also, except for 21, the prime power needs to have an even exponent. Otherwise, for example for 35 the sum of divisors is 1+3+9+27+81+243 = (1+3)+(9+27)+(81+243) = 1*4 + 9*4 + 81*4 = (1+9+81)*4. That's some multiplier times (1+thePrime). And even if the multiplier is 1, the (1+thePrime) is only a prime for thePrime=2.

So: Besides 2, the only good numbers are even-exponent prime-powers. And their sum of divisors (sod) is also easy to calculate.

Python code taking half a second to find the 310 numbers that lastchance also found:

from math import isqrt

N = 10**9

def isprime(n):
  return all(n%d for d in range(2, isqrt(n)+1))

good = {2}
for i in range(2, isqrt(N)+1):
  if isprime(i):
    e = 2
    while i**e <= N:
      sod = (i**(e+1) - 1) // (i - 1)
      if isprime(sod):
        good.add(i**e)
      e += 2

print(len(good))
print(*sorted(good))

Shortened output (Attempt This Online!):

310
2 4 9 16 25 (...) 978250729 982007569 984641641

C++ code, also prints 310:

#include <iostream>

bool isprime(int n) {
  for (int d=2; d<=n/d; d++)
    if (n%d == 0)
      return false;
  return true;
}

int main() {
  int n = 1'000'000'000;
  int good = 1;
  for (int i=2; i<=n/i; i++) {
    if (isprime(i)) {
      for (long long I = i*i; I <= n; I *= i*i) {
        long long sod = (I*i-1) / (i-1);
        good += isprime(sod);
      }
    }
  }
  std::cout << good << '\n';
}

Attempt This Online!

Sign up to request clarification or add additional context in comments.

4 Comments

It may not be obvious with the examples used in the question, but I don't think the intent was to only consider prime factors. Each example includes 1 and n as divisors. Take the example 30, its prime factors are 2,3,5. But it also has factors 1, 6, 10, 15, 30. So is the sum 10 or is it 72?
@MarkRansom Sounds like you misread this somehow. I'm computing the sum of all divisors.
You start by talking about "prime factors", and you have isprime(i) in your main loop. It's easy to believe you're talking about prime factors.
@MarkRansom That's because they're useful for this. Already the formula image is clearly not just the sum of the prime factors (that would just be Sum(p_i)).
2

If the number is odd then divisors pair off (to make an even sum) unless the central divisor is repeated (i.e. the number is square).

If the number is even then take out factors of 2 until it is odd. Then the number is of the form ODD.2r. The divisors of the odd number are as above, so will only produce an odd sum if it is square. Multipliers of 2 will not change the oddness or even-ness of the sum. If r is even then we are again checking a square. If r is odd then we check 2 times a square.

The following for N=1000'000'000. I believe that there are 310 such numbers (all squares, except 2). Probably someone can come up with a better idea for the even-number tests.

#include <iostream>
#include <cmath>
using namespace std;

using INT = unsigned long long;

//======================================================================

INT sumDivisors( INT num )
{
   INT sum = 1;
   if ( num != 1 ) sum += num;

   INT imax = sqrt( num + 0.5 );       // divisors come in pairs
   for ( INT i = 2; i <= imax; i++ )
   {
      if ( num % i == 0 )
      {
         INT ii = num / i;             // second divisor
         sum += i;
         if ( ii != i ) sum += ii;
      }
   }
   return sum;
}

//======================================================================

bool isPrime( INT n )
{
   if ( n < 2      ) return false;
   if ( n % 2 == 0 ) return n == 2;

   INT imax = sqrt( n + 0.5 );
   for ( INT i = 3; i <= imax; i += 2 )
   {
      if ( n % i == 0 ) return false;
   }
   return true;
}

//======================================================================

int main()
{
   INT counter = 0;
   INT N = 1000'000'000;
   for ( INT s = 1; s <= sqrt( N + 0.5 ); s++ )
   {
      INT i = s * s;                                       // test squares
      INT S = sumDivisors( i );
      if ( isPrime( S ) )
      {
         cout << i << ": " << S << '\n';
         counter++;
      }

      i = 2 * s * s;                                       // test twice a square
      if ( i > N ) continue;
      S = sumDivisors( i );
      if ( isPrime( S ) )
      {
         cout << "Additional " << i << ": " << S << '\n';
         counter++;
      }
   }
   cout << counter << '\n';
}

Output (final answer - at the bottom - 310)

Additional 2: 3
4: 7
9: 13
16: 31
25: 31
...
...
978250729: 978282007
982007569: 982038907
984641641: 984673021
310

5 Comments

Let sod = sum of divisors. Then sod(ODD*2) = sod(ODD) + sod(ODD) * 2 = sod(ODD) * 3. (You have the odd divisors, and each one can be multiplied by 2 to give another divisor.) So if ODD > 1, then sod(ODD) > 1 and thus sod(ODD*2) isn't prime. And similar with higher powers of 2.
So the only even numbers you need to check are powers of 2.
And (besides the number 2), only even-exponent powers of 2 are candidates. For example with exponent 5, you have sod(2^5) = 1+2+4+8+16+32 = (1+2) + (4+8) + (16+32) = 3 + 4*3 + 16*3 = 21*3, which isn't prime.
Thanks for that. The even-exponent powers of 2 are squares, so covered in the existing loop (which doesn't distinguish even-odd). The search space can probably be reduced further, but it didn't take long to run. The code is a bit spartan - my full version had a lot more checking routines in.
Ha, actually prime factor 2 is nothing special here. We can do the same arguments with others. So we can't mix prime factors, the only candidates are even-exponent prime-powers.
-1

When you do not know whether the sum is prime or not, then you need to actually compute it.

However, there are general ideas that you can apply, such as:

  • if the sum has a pair amount of odd divisor types, then it's divisible with two, hence you do not need to check whether it's prime, you'll instantly know whether it's prime (equals 2) or not

Such ideas can be applied to drastically reduce the number of sums whose prime-ness you are to check. If such quickening rules fail to determine for a sum whether it's prime, then you will need to do the costly prime calculation, but it would be a much rarer necessity, than without these pre-filters.

14 Comments

How does that "divisible by 3" rule help? Computing the digit sum seems to be far slower than simply checking whether the number itself is divisible.
These are rules which are quick for humans. Programming them to do them programmatically and at least as efficient as the usual check seems like a challenge. Achieving better than (n log n) this way seems ... unlikely.
There is no need to check a lot of numbers. Primes are odd (except for 2), odd divisor sum is possible only for squares (except for 2 again).
@nocomment if you have a 10-digit number, then divisions are costly. Finding all the primes your large number is divisible with, looping to reach its square root will be way slower than adding 10 digits together.
@user58697 Yes, you are right, p² and 2*p²
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.