Search code examples
algorithmmathdata-structuresmodulonumber-theory

How to approach and understand a math related DSA question


I found this question online and I really have no idea what the question is even asking. I would really appreciate some help in first understanding the question, and a solution if possible. Thanks!

To see if a number is divisible by 3, you need to add up the digits of its decimal notation, and check if the sum is divisible by 3. To see if a number is divisible by 11, you need to split its decimal notation into pairs of digits (starting from the right end), add up corresponding numbers and check if the sum is divisible by 11.

For any prime p (except for 2 and 5) there exists an integer r such that a similar divisibility test exists: to check if a number is divisible by p, you need to split its decimal notation into r-tuples of digits (starting from the right end), add up these r-tuples and check whether their sum is divisible by p.

Given a prime int p, find the minimal r for which such divisibility test is valid and output it.

The input consists of a single integer p - a prime between 3 and 999983, inclusive, not equal to 5.

Example

input

3

output

1

input

11

output

2


Solution

  • This is a very cool problem! It uses modular arithmetic and some basic number theory to devise the solution.

    Let's say we have p = 11. What divisibility rule applies here? How many digits at once do we need to take, to have a divisibility rule?

    Well, let's try a single digit at a time. That would mean, that if we have 121 and we sum its digits 1 + 2 + 1, then we get 4. However we see, that although 121 is divisible by 11, 4 isn't and so the rule doesn't work.

    What if we take two digits at a time? With 121 we get 1 + 21 = 22. We see that 22 IS divisible by 11, so the rule might work here. And in fact, it does. For p = 11, we have r = 2.

    This requires a bit of intuition which I am unable to convey in text (I really have tried) but it can be proven that for a given prime p other than 2 and 5, the divisibility rule works for tuples of digits of length r if and only if the number 99...9 (with r nines) is divisible by p. And indeed, for p = 3 we have 9 % 3 = 0, while for p = 11 we have 9 % 11 = 9 (this is bad) and 99 % 11 = 0 (this is what we want).

    If we want to find such an r, we start with r = 1. We check if 9 is divisible by p. If it is, then we found the r. Otherwise, we go further and we check if 99 is divisible by p. If it is, then we return r = 2. Then, we check if 999 is divisible by p and if so, return r = 3 and so on. However, the 99...9 numbers can get very large. Thankfully, to check divisibility by p we only need to store the remainder modulo p, which we know is small (at least smaller than 999983). So the code in C++ would look something like this:

    int r(int p) {
      int result = 1;
      int remainder = 9 % p;
      while (remainder != 0) {
        remainder = (remainder * 10 + 9) % p;
        result++;
      }
      return result;
    }