public static String binomialCongruenceSteps(final int n, int a, final int m) {
        Algorithms.positiveCheck(n);
        Algorithms.positiveCheck(m);
        StringBuilder lineEnd = buildModLineEnd(m);
        final StringBuilder result = buildBinomialCongruence(1, 'x', n, 0, -a, lineEnd);
        if (m == 1)
            return result.append(INFINITE_SOLUTIONS).toString();        
        if (n == 1)
            return linearCongruenceSteps(1, a, m);
        if (n == 2)
            return quadraticCongruenceSimpleSteps('x', a, m);
        
        if (normalizeIntModuloChanges(a, m)) {
            a = Algorithms.normalizeIntModulo(a, m);
            result.append(buildBinomialCongruence(1, 'x', n, 0, -a, lineEnd));
        }
        result.append(SEPARATOR);
        if (!binomialCongruenceLemma(n, a, m, result))
            return result.append(NO_SOLUTION).toString();
        
        final List<Integer> solutions = Algorithms.binomialCongruence(n, a, m);
        if (solutions.isEmpty()) {
            final List<Pair<Integer, Integer>> factors = Algorithms.factorize(m);
            result.append(factorizeSteps(m)).append(NEWLINE);
            for (int i = 0; i < factors.size(); ++i) {
                final StringBuilder subResult = new StringBuilder();
                final int mi = factors.get(i).getFirst();
                if (!binomialCongruenceLemma(n, a, mi, subResult)) {
                    result.append(subResult);
                    break;
                }
            }
            return result.append(NO_SOLUTION).toString();
        }
        
        final int lastIndex = solutions.size() - 1;
        lineEnd = buildModLineEnd(solutions.get(lastIndex));
        for (int i = 0; i < lastIndex; ++i) {
            result.append(buildLinearCongruence(1, 'x', solutions.get(i), lineEnd));
        }
        return result.toString();
    }