import java.util.*;

public class Euler236 {
    static final long[] A = { 5248, 1312, 2624, 5760, 3936 };
    static final long[] B = { 640, 1888, 3776, 3776, 5664 };

    static final int GROUPS = 3;
    static final int[][] GROUP_PRODUCTS = {
            { 0, -1, -1 },
            { 1, 2, 4 },
            { 3, -1, -1 }
    };
    static final int[] GROUP_SIZE = { 1, 3, 1 };
    static final long[] GROUP_B_NUM = { 5, 59, 59 };
    static final long[] GROUP_A_DEN = { 41, 41, 90 };

    static final long SA = 18880;
    static final long SB = 15744;

    static long gcd(long a, long b) {
        if (b == 0)
            return Math.abs(a);
        return gcd(b, a % b);
    }

    static class Fraction implements Comparable<Fraction> {
        long u, v;

        Fraction(long u, long v) {
            if (v < 0) {
                u = -u;
                v = -v;
            }
            long g = gcd(u, v);
            this.u = u / g;
            this.v = v / g;
        }

        @Override
        public int compareTo(Fraction o) {
            // u/v < o.u/o.v -> u*o.v < o.u*v
            // use BigInteger or double if overflow can happen, but here it fits in long?
            // Max u,v are around 5000. So 5000*5000 fits easily in long.
            long diff = this.u * o.v - o.u * this.v;
            return Long.compare(diff, 0);
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof Fraction))
                return false;
            Fraction o = (Fraction) obj;
            return u == o.u && v == o.v;
        }
    }

    static long floorDiv(long a, long b) {
        long q = a / b;
        long r = a % b;
        if (r != 0 && ((r > 0) != (b > 0))) {
            q--;
        }
        return q;
    }

    static long ceilDiv(long a, long b) {
        return -floorDiv(-a, b);
    }

    static long[] extendedGcd(long a, long b) {
        if (b == 0) {
            return new long[] { a >= 0 ? 1 : -1, 0, Math.abs(a) };
        }
        long[] res = extendedGcd(b, a % b);
        long x1 = res[0];
        long y1 = res[1];
        long g = res[2];
        return new long[] { y1, x1 - (a / b) * y1, g };
    }

    static long[] tightenRange(long p, long q, long low, long high, long tLow, long tHigh) {
        if (low > high)
            return new long[] { 0, tLow, tHigh };
        if (q == 0) {
            if (p >= low && p <= high)
                return new long[] { 1, tLow, tHigh };
            return new long[] { 0, tLow, tHigh };
        }

        long l = 0, r = 0;
        if (q > 0) {
            l = ceilDiv(low - p, q);
            r = floorDiv(high - p, q);
        } else {
            l = ceilDiv(high - p, q);
            r = floorDiv(low - p, q);
        }

        if (l > r)
            return new long[] { 0, tLow, tHigh };
        if (l > tLow)
            tLow = l;
        if (r < tHigh)
            tHigh = r;

        return new long[] { tLow <= tHigh ? 1 : 0, tLow, tHigh };
    }

    static boolean existsBoundedLinear(long c1, long l1, long h1, long c2, long l2, long h2, long rhs) {
        if (l1 > h1 || l2 > h2)
            return false;
        if (c1 == 0 && c2 == 0)
            return rhs == 0;
        if (c1 == 0) {
            if (rhs % c2 != 0)
                return false;
            long s2 = rhs / c2;
            return s2 >= l2 && s2 <= h2;
        }
        if (c2 == 0) {
            if (rhs % c1 != 0)
                return false;
            long s1 = rhs / c1;
            return s1 >= l1 && s1 <= h1;
        }

        long[] res = extendedGcd(c1, c2);
        long x0 = res[0];
        long y0 = res[1];
        long g = res[2];

        if (rhs % g != 0)
            return false;

        long scale = rhs / g;
        long step1 = c2 / g;
        long step2 = -c1 / g;

        // Ensure no overflow
        long base1 = x0 * scale;
        long base2 = y0 * scale;

        long tLow = Long.MIN_VALUE / 4;
        long tHigh = Long.MAX_VALUE / 4;

        long[] tr1 = tightenRange(base1, step1, l1, h1, tLow, tHigh);
        if (tr1[0] == 0)
            return false;
        tLow = tr1[1];
        tHigh = tr1[2];

        long[] tr2 = tightenRange(base2, step2, l2, h2, tLow, tHigh);
        if (tr2[0] == 0)
            return false;
        tLow = tr2[1];
        tHigh = tr2[2];

        return tLow <= tHigh;
    }

    static Fraction[] generateCandidates() {
        List<Fraction> out = new ArrayList<>();
        for (long a = 1; a <= A[0]; ++a) {
            for (long b = 1; b <= B[0]; ++b) {
                Fraction m = new Fraction(41 * b, 5 * a);
                if (m.u > m.v) {
                    out.add(m);
                }
            }
        }
        Collections.sort(out);
        List<Fraction> unique = new ArrayList<>();
        for (int i = 0; i < out.size(); ++i) {
            if (i == 0 || !out.get(i).equals(out.get(i - 1))) {
                unique.add(out.get(i));
            }
        }
        return unique.toArray(new Fraction[0]);
    }

    static boolean candidateWorks(Fraction m) {
        if (m.u <= m.v)
            return false;

        long[] minSum = { 1, 3, 1 };
        long[] maxSum = { 0, 0, 0 };
        long[] coef = { 0, 0, 0 };

        for (int g = 0; g < GROUPS; ++g) {
            Fraction groupRatio = new Fraction(m.u * GROUP_B_NUM[g], m.v * GROUP_A_DEN[g]);
            long N = groupRatio.u;
            long D = groupRatio.v;

            long upperSum = 0;
            for (int j = 0; j < GROUP_SIZE[g]; ++j) {
                int idx = GROUP_PRODUCTS[g][j];
                long upper = Math.min(A[idx] / D, B[idx] / N);
                if (upper < 1)
                    return false;
                upperSum += upper;
            }
            maxSum[g] = upperSum;
            coef[g] = m.v * SB * D - m.u * SA * N;
        }

        for (long s0 = minSum[0]; s0 <= maxSum[0]; ++s0) {
            long rhs = -(coef[0] * s0);
            if (existsBoundedLinear(coef[1], minSum[1], maxSum[1], coef[2], minSum[2], maxSum[2], rhs)) {
                return true;
            }
        }

        return false;
    }

    public static String solve() {
        Fraction[] candidates = generateCandidates();
        List<Fraction> solutions = new ArrayList<>();

        // Multi-threading could be used, but since we're porting directly and Python
        // runs it fairly fast
        for (Fraction cand : candidates) {
            if (candidateWorks(cand)) {
                solutions.add(cand);
            }
        }

        if (solutions.isEmpty()) {
            return "No solution";
        }

        Fraction best = solutions.get(solutions.size() - 1);
        return best.u + "/" + best.v;
    }

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