import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Euler456 {

    static class Dir {
        int x, y;
        long w;

        Dir(int x, int y, long w) {
            this.x = x;
            this.y = y;
            this.w = w;
        }
    }

    static int gcd(int a, int b) {
        a = Math.abs(a);
        b = Math.abs(b);
        while (b != 0) {
            int t = a % b;
            a = b;
            b = t;
        }
        return a;
    }

    static int halfPlane(Dir d) {
        return (d.y > 0 || (d.y == 0 && d.x > 0)) ? 0 : 1;
    }

    static class LexCmp implements Comparator<Dir> {
        public int compare(Dir a, Dir b) {
            if (a.x != b.x)
                return Integer.compare(a.x, b.x);
            return Integer.compare(a.y, b.y);
        }
    }

    static class AngleCmp implements Comparator<Dir> {
        public int compare(Dir a, Dir b) {
            int ha = halfPlane(a);
            int hb = halfPlane(b);
            if (ha != hb) {
                return Integer.compare(ha, hb);
            }
            long cross = (long) a.x * b.y - (long) a.y * b.x;
            if (cross > 0)
                return -1;
            if (cross < 0)
                return 1;
            return 0;
        }
    }

    public static String solve() {
        int n = 2000000;
        Dir[] rawDirs = new Dir[n];

        long xMod = 1248 % 32323;
        long yMod = 8421 % 30103;

        for (int i = 0; i < n; i++) {
            int x = (int) xMod - 16161;
            int y = (int) yMod - 15051;
            int g = gcd(x, y);
            rawDirs[i] = new Dir(x / g, y / g, 1);

            xMod = (xMod * 1248L) % 32323L;
            yMod = (yMod * 8421L) % 30103L;
        }

        Arrays.parallelSort(rawDirs, new LexCmp());

        List<Dir> uniqueLex = new ArrayList<>();
        for (Dir p : rawDirs) {
            if (!uniqueLex.isEmpty()) {
                Dir back = uniqueLex.get(uniqueLex.size() - 1);
                if (back.x == p.x && back.y == p.y) {
                    back.w++;
                } else {
                    uniqueLex.add(p);
                }
            } else {
                uniqueLex.add(p);
            }
        }

        java.math.BigInteger W = java.math.BigInteger.ZERO;
        java.math.BigInteger S2 = java.math.BigInteger.ZERO;
        java.math.BigInteger S3 = java.math.BigInteger.ZERO;

        for (Dir d : uniqueLex) {
            java.math.BigInteger w = java.math.BigInteger.valueOf(d.w);
            W = W.add(w);
            S2 = S2.add(w.multiply(w));
            S3 = S3.add(w.multiply(w).multiply(w));
        }

        java.math.BigInteger totalDistinct = W.pow(3)
                .subtract(java.math.BigInteger.valueOf(3).multiply(W).multiply(S2))
                .add(java.math.BigInteger.valueOf(2).multiply(S3))
                .divide(java.math.BigInteger.valueOf(6));

        java.math.BigInteger boundary = java.math.BigInteger.ZERO;

        int numUnique = uniqueLex.size();
        for (int i = 0; i < numUnique; i++) {
            Dir d = uniqueLex.get(i);
            int ox = -d.x;
            int oy = -d.y;

            Dir searchKey = new Dir(ox, oy, 0);
            int idx = Collections.binarySearch(uniqueLex, searchKey, new LexCmp());

            if (idx >= 0) {
                if (d.x < ox || (d.x == ox && d.y < oy)) {
                    java.math.BigInteger wi = java.math.BigInteger.valueOf(d.w);
                    java.math.BigInteger wj = java.math.BigInteger.valueOf(uniqueLex.get(idx).w);
                    boundary = boundary.add(wi.multiply(wj).multiply(W.subtract(wi).subtract(wj)));
                }
            }
        }

        Dir[] byAngle = uniqueLex.toArray(new Dir[0]);
        Arrays.parallelSort(byAngle, new AngleCmp());

        int m = byAngle.length;
        long[] weight2 = new long[2 * m];
        for (int i = 0; i < m; i++) {
            weight2[i] = byAngle[i].w;
            weight2[i + m] = byAngle[i].w;
        }

        long[] prefW = new long[2 * m + 1];
        long[] prefW2 = new long[2 * m + 1];
        for (int i = 0; i < 2 * m; i++) {
            prefW[i + 1] = prefW[i] + weight2[i];
            prefW2[i + 1] = prefW2[i] + weight2[i] * weight2[i];
        }

        Dir[] angle2 = new Dir[2 * m];
        System.arraycopy(byAngle, 0, angle2, 0, m);
        System.arraycopy(byAngle, 0, angle2, m, m);

        java.math.BigInteger outsideOpen = java.math.BigInteger.ZERO;
        int j = 0;

        for (int i = 0; i < m; i++) {
            if (j < i + 1) {
                j = i + 1;
            }
            Dir a = angle2[i];
            while (j < i + m) {
                Dir b = angle2[j];
                long cross = (long) a.x * b.y - (long) a.y * b.x;
                if (cross > 0) {
                    j++;
                } else {
                    break;
                }
            }

            java.math.BigInteger sVal = java.math.BigInteger.valueOf(prefW[j] - prefW[i + 1]);
            java.math.BigInteger ssVal = java.math.BigInteger.valueOf(prefW2[j] - prefW2[i + 1]);
            java.math.BigInteger pairWeight = sVal.multiply(sVal).subtract(ssVal)
                    .divide(java.math.BigInteger.valueOf(2));

            outsideOpen = outsideOpen.add(java.math.BigInteger.valueOf(angle2[i].w).multiply(pairWeight));
        }

        java.math.BigInteger ans = totalDistinct.subtract(outsideOpen).subtract(boundary);
        return ans.toString();
    }

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