import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.*;

public class Euler566 {
    static long gcd(long a, long b) {
        while (b != 0) {
            long t = a % b;
            a = b;
            b = t;
        }
        return a < 0 ? -a : a;
    }

    static long lcm(long a, long b) {
        if (a == 0 || b == 0)
            return 0;
        return (a / gcd(a, b)) * b;
    }

    static class Point {
        long P, Q;

        Point(long P, long Q) {
            this.P = P;
            this.Q = Q;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o)
                return true;
            if (!(o instanceof Point))
                return false;
            Point point = (Point) o;
            return P == point.P && Q == point.Q;
        }

        @Override
        public int hashCode() {
            long x = P * 0x9e3779b97f4a7c15L;
            long y = Q + 0x9e3779b97f4a7c15L;
            x ^= y + 0x9e3779b97f4a7c15L + (x << 6) + (x >>> 2);
            return (int) (x ^ (x >>> 32));
        }
    }

    static int signABsqrtc(long A, long B, int c) {
        if (B == 0) {
            if (A == 0)
                return 0;
            return (A > 0) ? 1 : -1;
        }
        if (A == 0)
            return (B > 0) ? 1 : -1;
        if ((A > 0 && B > 0) || (A < 0 && B < 0))
            return (A > 0) ? 1 : -1;

        long A2_lo = A * A;
        long A2_hi = Math.multiplyHigh(A, A);

        long B2_lo = B * B;
        long B2_hi = Math.multiplyHigh(B, B);

        long B2c_lo = B2_lo * c;
        long B2c_hi = B2_hi * c + Math.multiplyHigh(B2_lo, c) + ((B2_lo < 0) ? c : 0);

        int cmp;
        if (B2c_hi != A2_hi) {
            cmp = (B2c_hi > A2_hi) ? 1 : -1;
        } else {
            cmp = (B2c_lo + Long.MIN_VALUE > A2_lo + Long.MIN_VALUE) ? 1 : ((B2c_lo == A2_lo) ? 0 : -1);
        }

        if (A < 0 && B > 0) {
            if (cmp == 0)
                return 0;
            return (cmp > 0) ? 1 : -1;
        }
        if (cmp == 0)
            return 0;
        return (cmp > 0) ? -1 : 1;
    }

    static int cmpPoints(Point a, Point b, long ab, int c) {
        long dP = a.P - b.P;
        long dQ = a.Q - b.Q;
        long A = dP * c;
        long B = dQ * ab;
        return signABsqrtc(A, B, c);
    }

    static class FieldContext {
        int a, b, c;
        long ab;
        double sqrtc;

        FieldContext(int a, int b, int c) {
            this.a = a;
            this.b = b;
            this.c = c;
            this.ab = (long) a * b;
            this.sqrtc = Math.sqrt(c);
        }
    }

    static Point canonical01(long P, long Q, FieldContext ctx) {
        double approx = ((double) P / ctx.ab) + ((double) Q * ctx.sqrtc / ctx.c);
        long n = (long) Math.floor(approx);
        P -= n * ctx.ab;

        while (signABsqrtc(P * ctx.c, Q * ctx.ab, ctx.c) < 0) {
            P += ctx.ab;
        }
        while (signABsqrtc((P - ctx.ab) * ctx.c, Q * ctx.ab, ctx.c) >= 0) {
            P -= ctx.ab;
        }
        return new Point(P, Q);
    }

    static Point addP(Point x, Point s, FieldContext ctx) {
        return canonical01(x.P + s.P, x.Q + s.Q, ctx);
    }

    static Point subP(Point x, Point s, FieldContext ctx) {
        return canonical01(x.P - s.P, x.Q - s.Q, ctx);
    }

    static Point oneMinus(Point x, FieldContext ctx) {
        return canonical01(ctx.ab - x.P, -x.Q, ctx);
    }

    static int[] kmpPrefix(byte[] pat) {
        int n = pat.length;
        int[] pi = new int[n];
        for (int i = 1, j = 0; i < n; i++) {
            while (j > 0 && pat[i] != pat[j])
                j = pi[j - 1];
            if (pat[i] == pat[j])
                j++;
            pi[i] = j;
        }
        return pi;
    }

    static List<Integer> findRotations(byte[] w, byte[] e) {
        int n = w.length;
        byte[] text = new byte[2 * n];
        for (int i = 0; i < n; i++) {
            text[i] = w[i];
            text[i + n] = w[i];
        }
        int[] pi = kmpPrefix(e);
        List<Integer> shifts = new ArrayList<>();
        for (int i = 0, j = 0; i < 2 * n - 1; i++) {
            while (j > 0 && text[i] != e[j])
                j = pi[j - 1];
            if (text[i] == e[j])
                j++;
            if (j == n) {
                int pos = i - n + 1;
                if (pos < n) {
                    shimsAdd(shifts, (n - pos) % n);
                }
                j = pi[j - 1];
            }
        }
        return shifts;
    }

    static void shimsAdd(List<Integer> list, int val) {
        list.add(val);
    }

    static long[] egcdExt(long a, long b) {
        if (b == 0)
            return new long[] { 1, 0, a };
        long[] res = egcdExt(b, a % b);
        long x1 = res[0];
        long y1 = res[1];
        long g = res[2];
        long x = y1;
        long y = x1 - (a / b) * y1;
        return new long[] { x, y, g };
    }

    static long[] crtPair(long a1, long m1, long a2, long m2) {
        long g = gcd(m1, m2);
        long diff = a2 - a1;
        if (diff % g != 0)
            return null;
        long m1g = m1 / g;
        long m2g = m2 / g;

        long[] res = egcdExt(m1g, m2g);
        long x = res[0] % m2g;
        if (x < 0)
            x += m2g;

        BigInteger bigX = BigInteger.valueOf(x);
        BigInteger bigDiffG = BigInteger.valueOf(diff / g);
        BigInteger bigM2g = BigInteger.valueOf(m2g);

        BigInteger tBig = bigDiffG.multiply(bigX).remainder(bigM2g);
        if (tBig.compareTo(BigInteger.ZERO) < 0)
            tBig = tBig.add(bigM2g);

        BigInteger m1G = BigInteger.valueOf(m1 / g);
        BigInteger M = m1G.multiply(BigInteger.valueOf(m2));
        BigInteger A = BigInteger.valueOf(a1).add(BigInteger.valueOf(m1).multiply(tBig)).remainder(M);
        if (A.compareTo(BigInteger.ZERO) < 0)
            A = A.add(M);

        return new long[] { A.longValue(), M.longValue() };
    }

    static class CRTRes {
        List<Long> sols;
        long M;

        CRTRes(List<Long> sols, long M) {
            this.sols = sols;
            this.M = M;
        }
    }

    static CRTRes mergeCRT(List<Long> sols, long M, List<Long> residues, long P) {
        List<Long> next = new ArrayList<>();
        long newM = lcm(M, P);
        for (long s : sols) {
            for (long r : residues) {
                long[] am = crtPair(s, M, r, P);
                if (am != null) {
                    next.add(am[0]);
                }
            }
        }
        Set<Long> set = new HashSet<>(next);
        next = new ArrayList<>(set);
        Collections.sort(next);
        return new CRTRes(next, newM);
    }

    static class CycleRes {
        long P;
        List<Long> good;

        CycleRes(long P, List<Long> good) {
            this.P = P;
            this.good = good;
        }
    }

    static CycleRes cycleConstraint(byte[] f) {
        int L = f.length;
        int n = L / 3;
        byte totalF = 0;
        for (byte b : f)
            totalF ^= b;
        long P = (totalF == 0) ? L : 2L * L;

        byte[] a = new byte[n], b = new byte[n], c = new byte[n];
        for (int i = 0; i < n; i++) {
            a[i] = f[3 * i];
            b[i] = f[3 * i + 1];
            c[i] = f[3 * i + 2];
        }

        byte[] w = new byte[n];
        byte totalW = 0;
        for (int i = 0; i < n; i++) {
            w[i] = (byte) (a[i] ^ b[i] ^ c[i]);
            totalW ^= w[i];
        }

        byte[] pref = new byte[n + 1];
        for (int i = 0; i < n; i++)
            pref[i + 1] = (byte) (pref[i] ^ w[i]);

        List<Long> good = new ArrayList<>();
        for (int R = 0; R < 3; ++R) {
            byte[] t = new byte[n];
            if (R == 1) {
                System.arraycopy(a, 0, t, 0, n);
            } else if (R == 2) {
                for (int i = 0; i < n; i++)
                    t[i] = (byte) (a[i] ^ b[i]);
            }

            byte[] dt = new byte[n];
            for (int i = 0; i < n; i++)
                dt[i] = (byte) (t[i] ^ t[(i + 1) % n]);
            byte[] e = new byte[n];
            for (int i = 0; i < n; i++)
                e[i] = (byte) (w[i] ^ dt[i]);

            List<Integer> shifts = findRotations(w, e);
            for (int sShift : shifts) {
                for (int q = 0; q < 2; ++q) {
                    int mTrip = sShift + q * n;
                    byte h0 = (byte) (pref[sShift] ^ (q * totalW % 2));
                    byte target = t[mTrip % n];
                    if (h0 != target)
                        continue;
                    long N_val = 3L * mTrip + R;
                    long Nmod = N_val % P;
                    good.add(Nmod);
                }
            }
        }
        Set<Long> set = new HashSet<>(good);
        good = new ArrayList<>(set);
        Collections.sort(good);
        return new CycleRes(P, good);
    }

    static long F_square(int a, int b, int c) {
        int k = (int) Math.round(Math.sqrt(c));
        long D = 1;
        D = lcm(D, a);
        D = lcm(D, b);
        D = lcm(D, k);

        long[] S = { D / a, D / b, D / k };
        int m = (int) D;
        int N = 3 * m;
        int[] nxt = new int[N];
        byte[] flip = new byte[N];

        for (int ph = 0; ph < 3; ++ph) {
            long Sph = S[ph];
            for (int j = 0; j < m; ++j) {
                int j2;
                byte fbit;
                if (j < Sph) {
                    j2 = m - 1 - j;
                    fbit = 1;
                } else {
                    j2 = j - (int) Sph;
                    fbit = 0;
                }
                int cur = ph * m + j;
                int nxtph = (ph + 1) % 3;
                nxt[cur] = nxtph * m + j2;
                flip[cur] = fbit;
            }
        }

        boolean[] vis = new boolean[N];
        List<CycleRes> constraints = new ArrayList<>();

        for (int s = 0; s < N; ++s) {
            if (vis[s])
                continue;
            List<Integer> cyc = new ArrayList<>();
            int cur = s;
            while (!vis[cur]) {
                vis[cur] = true;
                cyc.add(cur);
                cur = nxt[cur];
            }
            int rot = 0;
            for (int i = 0; i < cyc.size(); i++) {
                if (cyc.get(i) < m) {
                    rot = i;
                    break;
                }
            }
            Collections.rotate(cyc, -rot);
            byte[] fCyc = new byte[cyc.size()];
            for (int i = 0; i < cyc.size(); i++)
                fCyc[i] = flip[cyc.get(i)];
            constraints.add(cycleConstraint(fCyc));
        }

        constraints.sort((x, y) -> Long.compare(x.P, y.P));

        long M = 1;
        List<Long> sols = new ArrayList<>();
        sols.add(0L);
        for (CycleRes cc : constraints) {
            CRTRes r = mergeCRT(sols, M, cc.good, cc.P);
            sols = r.sols;
            M = r.M;
        }

        long best = Long.MAX_VALUE;
        for (long r : sols) {
            if (r == 0)
                continue;
            if (r < best)
                best = r;
        }
        if (best == Long.MAX_VALUE)
            best = M;
        return best;
    }

    static int findIntervalIndex(List<Point> pts, Point x, FieldContext ctx) {
        int lo = 0;
        int hi = pts.size();
        while (lo + 1 < hi) {
            int mid = (lo + hi) / 2;
            if (cmpPoints(pts.get(mid), x, ctx.ab, ctx.c) <= 0) {
                lo = mid;
            } else {
                hi = mid;
            }
        }
        return lo;
    }

    static long F_nonsquare(int a, int b, int c) {
        FieldContext ctx = new FieldContext(a, b, c);

        Point s0 = canonical01(ctx.ab / a, 0, ctx);
        Point s1 = canonical01(ctx.ab / b, 0, ctx);
        Point s2 = canonical01(0, 1, ctx);
        Point[] sArr = { s0, s1, s2 };
        Point[] thr = { oneMinus(s0, ctx), oneMinus(s1, ctx), oneMinus(s2, ctx) };

        @SuppressWarnings("unchecked")
        Set<Point>[] sets = new HashSet[3];
        @SuppressWarnings("unchecked")
        List<Point>[] stack = new ArrayList[3];

        for (int ph = 0; ph < 3; ++ph) {
            sets[ph] = new HashSet<>();
            stack[ph] = new ArrayList<>();
            Point p0 = new Point(0, 0);
            sets[ph].add(p0);
            sets[ph].add(sArr[ph]);
            stack[ph].add(p0);
            stack[ph].add(sArr[ph]);
        }

        while (true) {
            boolean progressed = false;
            for (int ph = 0; ph < 3; ++ph) {
                while (!stack[ph].isEmpty()) {
                    progressed = true;
                    Point y = stack[ph].remove(stack[ph].size() - 1);
                    int prev = (ph + 2) % 3;
                    int cmp = cmpPoints(y, thr[prev], ctx.ab, ctx.c);
                    if (cmp < 0) {
                        Point x = addP(y, sArr[prev], ctx);
                        if (sets[prev].add(x))
                            stack[prev].add(x);
                    }
                    if (cmp > 0) {
                        Point x = oneMinus(y, ctx);
                        if (sets[prev].add(x))
                            stack[prev].add(x);
                    }
                }
            }
            if (!progressed)
                break;
        }

        @SuppressWarnings("unchecked")
        List<Point>[] pts = new ArrayList[3];
        int m = -1;
        for (int ph = 0; ph < 3; ++ph) {
            pts[ph] = new ArrayList<>(sets[ph]);
            pts[ph].sort((u, v) -> cmpPoints(u, v, ctx.ab, ctx.c));
            if (m < 0)
                m = pts[ph].size();
            if (m != pts[ph].size()) {
                return -1;
            }
        }

        int N = 3 * m;
        int[] nxt = new int[N];
        byte[] flip = new byte[N];

        for (int ph = 0; ph < 3; ++ph) {
            for (int i = 0; i < m; ++i) {
                Point l = pts[ph].get(i);
                Point r = (i + 1 < m) ? pts[ph].get(i + 1) : new Point(ctx.ab, 0);
                boolean inside = cmpPoints(l, sArr[ph], ctx.ab, ctx.c) < 0;
                Point yLeft = inside ? oneMinus(r, ctx) : subP(l, sArr[ph], ctx);
                int nxtph = (ph + 1) % 3;
                int j = findIntervalIndex(pts[nxtph], yLeft, ctx);
                int cur = ph * m + i;
                nxt[cur] = nxtph * m + j;
                flip[cur] = (byte) (inside ? 1 : 0);
            }
        }

        boolean[] vis = new boolean[N];
        List<CycleRes> constraints = new ArrayList<>();

        for (int sIdx = 0; sIdx < N; ++sIdx) {
            if (vis[sIdx])
                continue;
            List<Integer> cyc = new ArrayList<>();
            int cur = sIdx;
            while (!vis[cur]) {
                vis[cur] = true;
                cyc.add(cur);
                cur = nxt[cur];
            }

            int rot = 0;
            for (int i = 0; i < cyc.size(); i++) {
                if (cyc.get(i) < m) {
                    rot = i;
                    break;
                }
            }
            Collections.rotate(cyc, -rot);

            byte[] fCyc = new byte[cyc.size()];
            for (int i = 0; i < cyc.size(); i++)
                fCyc[i] = flip[cyc.get(i)];
            constraints.add(cycleConstraint(fCyc));
        }

        constraints.sort((x, y) -> Long.compare(x.P, y.P));

        long M = 1;
        List<Long> sols = new ArrayList<>();
        sols.add(0L);
        for (CycleRes cc : constraints) {
            CRTRes r = mergeCRT(sols, M, cc.good, cc.P);
            sols = r.sols;
            M = r.M;
        }

        long best = Long.MAX_VALUE;
        for (long r : sols) {
            if (r == 0)
                continue;
            if (r < best)
                best = r;
        }
        if (best == Long.MAX_VALUE)
            best = M;
        return best;
    }

    static boolean isSquare(int c) {
        int r = (int) Math.round(Math.sqrt(c));
        return r * r == c;
    }

    static long F(int a, int b, int c) {
        if (isSquare(c))
            return F_square(a, b, c);
        return F_nonsquare(a, b, c);
    }

    static BigInteger computeG(int n) {
        List<Callable<BigInteger>> tasks = new ArrayList<>();
        for (int a = 9; a <= n - 2; a++) {
            final int currA = a;
            tasks.add(() -> {
                BigInteger local = BigInteger.ZERO;
                for (int b = currA + 1; b <= n - 1; b++) {
                    for (int c = b + 1; c <= n; c++) {
                        local = local.add(BigInteger.valueOf(F(currA, b, c)));
                    }
                }
                return local;
            });
        }

        ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        BigInteger total = BigInteger.ZERO;
        try {
            for (Future<BigInteger> res : executor.invokeAll(tasks)) {
                total = total.add(res.get());
            }
        } catch (Exception e) {
        }
        executor.shutdown();
        return total;
    }

    public static String solve() {
        return computeG(53).toString();
    }

    public static void main(String[] args) {
        System.out.println(solve());
    }
}
