Problem:
Score : 500 points

Problem Statement

We have N integers. The i-th number is A_i.

\{A_i\} is said to be pairwise coprime when GCD(A_i,A_j)=1 holds for every pair (i, j) such that 1\leq i < j \leq N.

\{A_i\} is said to be setwise coprime when \{A_i\} is not pairwise coprime but GCD(A_1,\ldots,A_N)=1.

Determine if \{A_i\} is pairwise coprime, setwise coprime, or neither.

Here, GCD(\ldots) denotes greatest common divisor.

Constraints

2 \leq N \leq 10^6

1 \leq A_i\leq 10^6

Input

Input is given from Standard Input in the following format:

N
A_1 \ldots A_N

Output

If \{A_i\} is pairwise coprime, print pairwise coprime; if \{A_i\} is setwise coprime, print setwise coprime; if neither, print not coprime.

Sample Input 1

3
3 4 5

Sample Output 1

pairwise coprime

GCD(3,4)=GCD(3,5)=GCD(4,5)=1, so they are pairwise coprime.

Sample Input 2

3
6 10 15

Sample Output 2

setwise coprime

Since GCD(6,10)=2, they are not pairwise coprime. However, since GCD(6,10,15)=1, they are setwise coprime.

Sample Input 3

3
6 10 16

Sample Output 3

not coprime

GCD(6,10,16)=2, so they are neither pairwise coprime nor setwise coprime.

Solution in Fortran (GNU Fortran 9.2.1) (judge verdict: Accepted)

module fast_prime_sieve
  implicit none
contains
  subroutine primes(p, m, n)
    integer, allocatable, intent(inout) :: p(:)
    integer, intent(inout) :: m
    integer, intent(in) :: n
    integer :: lp(n), pr(n), i, j
    lp(n) = 0
    m = 0
    do i = 2, n
      if (lp(i) == 0) then
        lp(i) = i
        m = m + 1
        pr(m) = i
      end if
      j = 1
      do j = 1, m
        if (pr(j) > lp(i) .or. i * pr(j) > n) exit
        lp(i * pr(j)) = pr(j)
      end do
    end do
    allocate(p(m))
    p = pr(1:m)
  end
end module fast_prime_sieve
module bisection
  implicit none
  integer, private, parameter :: intkind = 4
contains
  integer function lower_bound(a, b) result(res)
    integer(intkind), intent(in) :: a(:), b
    integer :: l, r, m
    l = 0
    r = size(a) + 1
    do while (r - l > 1)
      m = (l + r) / 2
      if (a(m) < b) then
        l = m
      else
        r = m
      end if
    end do
    res = r
  end
  integer function upper_bound(a, b) result(res)
    integer(intkind), intent(in) :: a(:), b
    integer :: l, r, m
    l = 0
    r = size(a) + 1
    do while (r - l > 1)
      m = (l + r) / 2
      if (a(m) > b) then
        r = m
      else
        l = m
      end if
    end do
    res = l
  end
end module bisection
module gcd_lcm
  implicit none
  integer, private, parameter :: intkind = 4
contains
  integer(intkind) function gcd(x, y) result(res)
    integer(intkind), intent(in) :: x, y
    integer(intkind) :: a, b
    a = max(abs(x), abs(y))
    b = min(abs(x), abs(y))
    res = a
    do while (b > 0)
      res = b
      b = mod(a, b)
      a = res
    end do
  end
  integer(intkind) function lcm(x, y) result(res)
    integer(intkind), intent(in) :: x, y
    res = x / gcd(x, y) * y
  end
end module gcd_lcm
program coprime
  use fast_prime_sieve
  use bisection
  use gcd_lcm
  implicit none
  integer :: n, m, d, q, i, j
  logical :: pairwise = .true.
  integer, allocatable :: a(:), p(:)
  logical, allocatable :: b(:)
  character(8), parameter :: x = 'pairwise', y = 'setwise ', z = 'not     '
  read(*,*) n
  allocate(a(n))
  read(*,*) a
  call primes(p, m, maxval(a(1:n)))
  allocate(b(m))
  b = .false.
  do i = 1, n
    d = a(i)
    do j = 1, m
      q = p(j)
      if (q * q > d) exit
      if (mod(d, q) == 0) then
        if (b(j)) then
          pairwise = .false.
          goto 100
        end if
        b(j) = .true.
        do while (mod(d, q) == 0)
          d = d / q
        end do
      end if
    end do
    if (d /= 1) then
      j = lower_bound(p, d)
      if (b(j)) then
        pairwise = .false.
        goto 100
      end if
      b(j) = .true.
    end if
  end do
  100 if (pairwise) then
    write(*,'(a)') 'pairwise coprime'
    stop
  end if
  d = a(1)
  do i = 2, n
    d = gcd(d, a(i))
  end do
  write(*,'(a)') trim(merge('setwise', 'not    ', d == 1)) // ' coprime'
end program coprime