import java.math.BigInteger;

public class Euler988 {
    private static long gcd(long a, long b) {
        while (b != 0) {
            long r = a % b;
            a = b;
            b = r;
        }
        return a;
    }

    private static boolean isRepresentable(long n, long a, long b) {
        for (long x = 0; x * a <= n; ++x) {
            if ((n - x * a) % b == 0) {
                return true;
            }
        }
        return false;
    }

    private static BigInteger bruteForce(long a, long b) {
        long[] gaps = new long[20];
        int gapCount = 0;
        for (long n = 1; n < a * b; ++n) {
            if (!isRepresentable(n, a, b)) {
                gaps[gapCount++] = n;
            }
        }

        if (gapCount > 20) {
            throw new IllegalStateException("Too many gaps for brute force");
        }

        boolean[][] attack = new boolean[gapCount][gapCount];
        for (int i = 0; i < gapCount; ++i) {
            for (int j = i + 1; j < gapCount; ++j) {
                boolean bad = isRepresentable(gaps[j] - gaps[i], a, b);
                attack[i][j] = bad;
                attack[j][i] = bad;
            }
        }

        BigInteger total = BigInteger.ZERO;
        long full = 1L << gapCount;
        for (long mask = 0; mask < full; ++mask) {
            boolean ok = true;
            BigInteger subtotal = BigInteger.ZERO;
            for (int i = 0; i < gapCount && ok; ++i) {
                if (((mask >>> i) & 1L) == 0L) {
                    continue;
                }
                subtotal = subtotal.add(BigInteger.valueOf(gaps[i]));
                long rest = mask & (~0L << (i + 1));
                while (rest != 0L) {
                    int j = Long.numberOfTrailingZeros(rest);
                    if (attack[i][j]) {
                        ok = false;
                        break;
                    }
                    rest &= rest - 1;
                }
            }
            if (ok) {
                total = total.add(subtotal);
            }
        }

        return total;
    }

    private static BigInteger solve(long a, long b) {
        if (a > b) {
            long tmp = a;
            a = b;
            b = tmp;
        }

        int ai = (int) a;
        long ab = a * b;

        BigInteger[] counts = new BigInteger[ai + 1];
        BigInteger[] sums = new BigInteger[ai + 1];
        for (int i = 0; i <= ai; ++i) {
            counts[i] = BigInteger.ZERO;
            sums[i] = BigInteger.ZERO;
        }
        counts[ai] = BigInteger.ONE;

        for (int x = 1; x < b; ++x) {
            int h = (int) ((ab - 1 - a * x) / b);
            BigInteger[] nextCounts = counts.clone();
            BigInteger[] nextSums = sums.clone();

            for (int limit = 1; limit <= ai; ++limit) {
                BigInteger count = counts[limit];
                if (count.signum() == 0) {
                    continue;
                }

                BigInteger prefixSum = sums[limit];
                int ymax = Math.min(h, limit - 1);
                for (int y = 1; y <= ymax; ++y) {
                    long gap = ab - a * x - b * y;
                    nextCounts[y] = nextCounts[y].add(count);
                    nextSums[y] = nextSums[y].add(prefixSum.add(count.multiply(BigInteger.valueOf(gap))));
                }
            }

            counts = nextCounts;
            sums = nextSums;
        }

        BigInteger answer = BigInteger.ZERO;
        for (BigInteger value : sums) {
            answer = answer.add(value);
        }
        return answer;
    }

    private static void require(boolean condition, String message) {
        if (!condition) {
            throw new IllegalStateException(message);
        }
    }

    private static void runCheckpoints() {
        for (long a = 2; a <= 7; ++a) {
            for (long b = a + 1; b <= 8; ++b) {
                if (gcd(a, b) != 1 || a * b > 35) {
                    continue;
                }
                require(solve(a, b).equals(bruteForce(a, b)), "Brute force mismatch");
                require(solve(a, b).equals(solve(b, a)), "Symmetry mismatch");
            }
        }

        require(solve(3, 5).equals(BigInteger.valueOf(23)), "Check solve(3,5)");
        require(solve(5, 13).equals(BigInteger.valueOf(16336)), "Check solve(5,13)");
    }

    public static void main(String[] args) {
        boolean shouldRunCheckpoints = true;
        for (String arg : args) {
            if ("--skip-checkpoints".equals(arg)) {
                shouldRunCheckpoints = false;
            }
        }

        if (shouldRunCheckpoints) {
            runCheckpoints();
        }

        System.out.println(solve(19, 53));
    }
}
