Codeforces Round 1133 (Div. 1, Div. 2) is coming soon! Register here. ×

tenebrix's blog

By tenebrix, 6 months ago, In English

Context: After reading the problem below, you might say there's a more optimal way to solve it. However, this note is meant to highlight a specific question: If you run a basic loop to solve this, will it actually get a TLE (Time Limit Exceeded) when given many test cases and no further restrictions?

Many beginners who don't know much about number theory might just brute-force it, and then wonder how their code actually passed. Let's see why.

Say you are given a number $$$n$$$ ($$$7 \le n \le 10^{18}$$$) and asked to find two distinct numbers $$$a$$$ and $$$b$$$ such that:

  • $$$a + b = n$$$
  • $$$\gcd(a,b) = 1$$$ (meaning $$$a$$$ and $$$b$$$ are coprimes)
  • Important: Neither $$$a$$$ nor $$$b$$$ can be 1.

Because we are strictly not allowed to use 1, the obvious choice of setting $$$a = 1$$$ and $$$b = n - 1$$$ is gone.

So let's look at the math. As we know via the Euclidean property: $$$\gcd(a,b) = \gcd(a, a+b)$$$

Since $$$a + b = n$$$, we can rewrite this as: $$$\gcd(a,b) = \gcd(a, n)$$$

Thus, our task simplifies: we just have to find a number coprime to $$$n$$$ which is greater than 1 and less than $$$n-1$$$.

Now finding a coprime to a given number n we might think it may take O(n) to iterate a loop of i=2 to i=n-2 and say if test cases t <= $$$10^5$$$ and no further restrictions on n and t — we might think of it as high complexity method but in actual — does it take O(n) ?

Let's see

the worst case scenario we fear — loop is running and we haven't found a number coprime to it -> which means it has all prime factors(2,3,5,7....23,29,31,37...) till that

but

a number having all primes till 29 is at least = 2*3*5*.....23*29 which exceeds $$$10^9$$$

a number having all primes till 53 is at least = 2*3*5*.....23*29...43*47*53 which exceeds $$$10^{18}$$$

thus we can say

  • if a loop runs till 47 and no coprime has been found :
    • we have 2 things guaranteed :
    • the number is near its limit $$$10^{18}$$$
    • the next prime 53 is coprime to n as if it isn't then it will exceed limit which isn't possible
  • else a loop doesn't run successfully till 47 and we have found a number coprime to n earlier than 47 iterations

Thus it takes less than 60 iterations which is O(1)

and its safe to run a loop of i=2 to i=n-2 or even better run

const int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};

to find a coprime number to given number n

Reference question : 1617B - GCD Problem (though this question also has a better approach than this one)

  • Vote: I like it
  • 0
  • Vote: I do not like it

»
6 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by tenebrix (previous revision, new revision, compare).

»
6 months ago, hide # |
 
Vote: I like it +7 Vote: I do not like it

learned what coprime numbers are, cool

but isn't a coprime js two numbers whose numbers (larger) % (smaller) = 1, so like 16 and 1 would be coprimes despite 16 not actually being a prime number

so if you are given a number and you have to find another number that is coprime you could always use 1 since every number mod 1 evaluated to 1? (I might be wrong, so sorry if that's not what ur asking)

  • »
    »
    6 months ago, hide # ^ |
    ← Rev. 3  
    Vote: I like it +5 Vote: I do not like it

    Partially correct. Two numbers $$$a$$$ and $$$b$$$ are coprime if $$$\gcd(a, b)=1$$$. It is true that by definition $$$1$$$ is coprime to $$$16$$$, but this solution is used in the context where one is unable to use the number $$$1$$$.

    Also, $$$16\bmod 1$$$ evaluates to $$$0$$$ because $$$1\mid 16$$$. $$$a\bmod b$$$ evaluates to $$$1$$$ if and only if the remainder of $$$a/b$$$ is $$$1$$$. It seems you are assuming $$$a\bmod b$$$ will evaluate to $$$1$$$ if $$$b\nmid a$$$, but this is untrue. For example, $$$5\bmod 3 = 2$$$ and $$$2\nmid 5$$$.

    If I remember correctly, 2167D - Yet Another Array Problem uses this technique as well!

    Apologies for any minor logical or syntactical issues

    • »
      »
      »
      6 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      yea I kinda realized that anything mod 1 js equals zero. Also in the case of not being able to use one couldn't you use sieve of eratherasnos or whatever his name is (idk if that's smth you could acc do, but ik it's related to finding primes from 1 to n)

      • »
        »
        »
        »
        6 months ago, hide # ^ |
         
        Vote: I like it 0 Vote: I do not like it

        You could, but as this post states, you only need to find primes up to and including $$$53$$$. This is a very inexpensive calculation so you could do it, or you could list out all primes by hand (as the post suggests). Using the Sieve of Eratosthenes just seems unneeded in this case but it will accomplish the goal.

        • »
          »
          »
          »
          »
          6 months ago, hide # ^ |
           
          Vote: I like it +10 Vote: I do not like it

          ty for helping me find my silly mistakes tho, so like 67 and 420 (hehe funny numbers) are coprime even though 420 % 67 isn't 1,cus they don't share a common divisor except 1. still getting used to this number theory math stuff

»
6 months ago, hide # |
 
Vote: I like it +8 Vote: I do not like it

Or you can choose n — 1.

  • »
    »
    6 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    what about when n = 2 and you can't use one as stated In the blog

  • »
    »
    6 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Thanks for reviewing

    I made the blog based on the question referred and i forgot to give a context of it

    and yes we could use n-1 and 1 as gcd(n-1,n)=1 and gcd(1,n)=1 for all n>=1

    but again in question we couldn't use it so i forgot to gave context

    just edited it . Thanks for pointing out .

»
6 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

using euler's function, maybe?

  • »
    »
    6 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Euler's requires finding all prime factors, which takes $$$O(\sqrt{n})$$$.

    If we change it to just break at the first n % i != 0 to save time,

    it ceases to be Euler's function and just becomes the exact $$$O(1)$$$ loop described in the blog.