package main
import (
"bufio"
"io"
"os"
"strconv"
)
func nextInt(data []byte, idx *int) int {
n := len(data)
for *idx < n {
c := data[*idx]
if c >= '0' && c <= '9' {
break
}
*idx++
}
val := 0
for *idx < n {
c := data[*idx]
if c < '0' || c > '9' {
break
}
val = val*10 + int(c-'0')
*idx++
}
return val
}
func buildSPF(n int) []uint32 {
spf := make([]uint32, n+1)
if n < 2 {
return spf
}
primes := make([]int, 0, 700000)
for i := 2; i <= n; i++ {
if spf[i] == 0 {
spf[i] = uint32(i)
primes = append(primes, i)
}
si := int(spf[i])
limit := n / i
for j := 0; j < len(primes); j++ {
p := primes[j]
if p > si || p > limit {
break
}
spf[p*i] = uint32(p)
}
}
return spf
}
func find(parent []uint32, x int) int {
for parent[x] != uint32(x) {
parent[x] = parent[int(parent[x])]
x = int(parent[x])
}
return x
}
func union(parent, size []uint32, a, b int, comps *int) {
ra := find(parent, a)
rb := find(parent, b)
if ra == rb {
return
}
if size[ra] < size[rb] {
ra, rb = rb, ra
}
parent[rb] = uint32(ra)
size[ra] += size[rb]
*comps = *comps - 1
}
func main() {
data, _ := io.ReadAll(os.Stdin)
ptr := 0
n := nextInt(data, &ptr)
vals := make([]int, n)
maxA := 0
needSieve := false
for i := 0; i < n; i++ {
x := nextInt(data, &ptr)
vals[i] = x
if x > maxA {
maxA = x
}
if x > 1 && ((x&1) == 1 || (x&3) == 0) {
needSieve = true
}
}
w := bufio.NewWriterSize(os.Stdout, 1<<20)
defer w.Flush()
if !needSieve {
w.WriteString(strconv.Itoa(n))
return
}
data = nil
idxByVal := make([]uint32, maxA+1)
for i, x := range vals {
idxByVal[x] = uint32(i + 1)
}
spf := buildSPF(maxA)
parent := make([]uint32, n)
size := make([]uint32, n)
for i := 0; i < n; i++ {
parent[i] = uint32(i)
size[i] = 1
}
comps := n
for i, x := range vals {
if x > 1 && (x&1) == 1 {
temp := x
var blocks [8]int
cnt := 0
for temp > 1 {
p := int(spf[temp])
pp := 1
for temp%p == 0 {
pp *= p
temp /= p
}
blocks[cnt] = pp
cnt++
}
lim := 1 << cnt
for mask := 0; mask < lim; mask++ {
s := 1
for j := 0; j < cnt; j++ {
if (mask>>j)&1 != 0 {
s *= blocks[j]
}
}
t := x / s
if s >= t {
continue
}
ss := int64(s)
tt := int64(t)
even := (tt*tt - ss*ss) >> 1
if even <= int64(maxA) {
id := idxByVal[int(even)]
if id != 0 {
union(parent, size, i, int(id-1), &comps)
}
}
hyp := (tt*tt + ss*ss) >> 1
if hyp <= int64(maxA) {
id := idxByVal[int(hyp)]
if id != 0 {
union(parent, size, i, int(id-1), &comps)
}
}
}
} else if (x & 3) == 0 {
k := x >> 1
temp := k
block2 := 1
for (temp & 1) == 0 {
block2 <<= 1
temp >>= 1
}
var blocks [8]int
cnt := 0
totalOdd := 1
for temp > 1 {
p := int(spf[temp])
pp := 1
for temp%p == 0 {
pp *= p
temp /= p
}
blocks[cnt] = pp
cnt++
totalOdd *= pp
}
lim := 1 << cnt
for mask := 0; mask < lim; mask++ {
prod := 1
for j := 0; j < cnt; j++ {
if (mask>>j)&1 != 0 {
prod *= blocks[j]
}
}
evenFactor := block2 * prod
oddFactor := totalOdd / prod
m := evenFactor
nn := oddFactor
if m < nn {
m, nn = nn, m
}
mm := int64(m)
n64 := int64(nn)
oddLeg := mm*mm - n64*n64
if oddLeg <= int64(maxA) {
id := idxByVal[int(oddLeg)]
if id != 0 {
union(parent, size, i, int(id-1), &comps)
}
}
hyp := mm*mm + n64*n64
if hyp <= int64(maxA) {
id := idxByVal[int(hyp)]
if id != 0 {
union(parent, size, i, int(id-1), &comps)
}
}
}
}
}
w.WriteString(strconv.Itoa(comps))
}