package cap09_sum_powers;

import java.io.*;
import java.util.*;

public class P01SumOfPowers {
  private static final String FileInputName = "psum.in";
  private static final String FileOutputName = "psum.out";
  private final static int MAX_NO = 20;

  private static void genCombinations(long C[][], int n) {
    C[0][0] = 1;
    for (int i = 1; i <= n; i++) {
      C[i][0] = C[i][i] = 1;
      for (int j = 1; j < i; j++)
        C[i][j] = C[i-1][j-1]+C[i-1][j];
    }
  }

public static void main(String args[]) throws IOException {
    Scanner scanner = null;
    PrintStream out = null;
    try {
      scanner = new Scanner(new File(FileInputName));
      out = new PrintStream(new File(FileOutputName));
      Fraction fr[] = new Fraction[MAX_NO+2];
      Fraction W[] = new Fraction[MAX_NO+1];
      long C[][] = new long[MAX_NO+2][MAX_NO+2];
      genCombinations(C, MAX_NO+1);
      long M[] = new long[MAX_NO+1], Q;
      M[0] = 1;
      long A[][] = new long[MAX_NO+1][MAX_NO+2];
      A[0][1] = 1;
      A[0][0] = 0;
      for (int p = 1; p <= MAX_NO; p++) {
        int sign = 1;
        for (int t = p-1; t >= 0; t--) {
          W[t] = new Fraction(sign*C[p+1][p+1-t], M[t]);
          sign *= -1;
        }
        for (int t = p; t >= 0; t--) {
          fr[t] =  new Fraction();
          for (int r = p-1; r >= t-1 && r >= 0; r--) {
            fr[t].add(W[r].multiply(A[r][t]));
          }
        }
        fr[p+1] = new Fraction(1, 1);
        Q = Fraction.lcmDenomin(fr, p+1);
        M[p] = (p+1)*Q;
        for (int t = p+1; t >= 0; t--) {
          A[p][t] = fr[t].multiply(Q).getNumerator();
        }
      }

      while (scanner.hasNextInt()) {
        int k = scanner.nextInt();
        out.print(M[k]);
        out.print(' ');
        for (int t = k+1; t >= 0; t--) {
          out.print(A[k][t]); out.print(' ');
        }
        out.println();
      }

    } finally {
      if (scanner != null) scanner.close();
      if (out != null) out.close();
    }
  }
}

class Fraction {
  private long numerator;
  private long denominator;

  Fraction(long numerator, long denominator) {
    this.numerator = numerator;
    this.denominator = denominator;
    this.simplify();
  }

  Fraction() {
    this.numerator = 0;
    this.denominator = 1;
  }
  
  long getNumerator(){
    return numerator;
  }
  
  void add(Fraction other){    
    this.numerator   = numerator*other.denominator+
                       denominator*other.numerator;
    this.denominator = denominator*other.denominator;
    this.simplify();
  }
    
  Fraction multiply(long n){
    return
      new Fraction(numerator*n, denominator);    
  }
  
  private static long gcd(long a, long b) {
    while (b != 0) {
      long r = a % b;
      a = b;
      b = r;
    }
    return a;
  }

  void simplify() throws ArithmeticException {
    long d = gcd(this.numerator, this.denominator);
    this.numerator /= d;
    this.denominator /= d;
    if (this.denominator < 0) {
      this.denominator *= -1;
      this.numerator *= -1;
    }
  }

  static long lcm(long a, long b) {
    return (a/gcd(a, b))*b;
  }

  static long lcmDenomin(Fraction fr[], int n) {
    long gcd = 1;
    if (n == 0)
      return 1;
    gcd = fr[0].denominator;
    for (int i = 1; i < n; i++) {
      gcd = lcm(gcd, fr[i].denominator);
    }
    return gcd;
  }
}


/*
import java.io.*;
import java.util.*;

public class P01SumOfPowers {
  private static final String FileInputName = "psum.in";
  private static final String FileOutputName = "psum.out";
  private final static int MAX_NO = 20;

  private static void genCombinations(long C[][], int n) {
    C[0][0] = 1;
    for (int i = 1; i <= n; i++) {
      C[i][0] = C[i][i] = 1;
      for (int j = 1; j < i; j++)
        C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
    }
  }

  public static void main(String args[]) throws IOException {
    Scanner scanner = null;
    PrintStream out = null;
    try {
      scanner = new Scanner(new File(FileInputName));
      out = new PrintStream(new File(FileOutputName));
      Fraction fr[] = new Fraction[MAX_NO + 2];
      for (int i = 0; i < fr.length; i++) {
        fr[i] = new Fraction();
      }
      Fraction W[] = new Fraction[MAX_NO + 1];
      for (int i = 0; i < W.length; i++) {
        W[i] = new Fraction();
      }
      Fraction fAux = new Fraction();
      Fraction fAux2 = new Fraction();
      long C[][] = new long[MAX_NO + 2][MAX_NO + 2];
      genCombinations(C, MAX_NO + 1);
      long M[] = new long[MAX_NO + 1], Q;
      M[0] = 1;
      long A[][] = new long[MAX_NO + 1][MAX_NO + 2];
      A[0][1] = 1;
      A[0][0] = 0;
      for (int p = 1; p <= MAX_NO; p++) {
        int sign = 1;
        for (int t = p - 1; t >= 0; t--) {
          W[t].copy(sign * C[p + 1][p + 1 - t], M[t]);
          sign *= -1;
        }
        for (int t = p; t >= 0; t--) {
          fAux.copy(0, 1);
          for (int r = p - 1; r >= t - 1 && r >= 0; r--) {
            fAux2 = W[r].multiply(A[r][t]);
            fAux.add(fAux2);
          }
          fr[t].copy(fAux);
        }
        fAux.copy(W[0].multiply(A[0][0]));
        fr[0].add(fAux);
        fr[p + 1].copy(1, 1);
        Q = Fraction.lcmDenomin(fr, p + 1);
        M[p] = (p + 1) * Q;
        for (int t = p + 1; t >= 0; t--) {
          fAux2.copy(fr[t].multiply(Q));
          A[p][t] = fAux2.getNumerator();
        }
      }

      while (scanner.hasNextInt()) {
        int k = scanner.nextInt();
        out.print(M[k]);
        out.print(' ');
        for (int t = k + 1; t >= 0; t--) {
          out.print(A[k][t]);
          out.print(' ');
        }
        out.println();
      }

    } finally {
      if (scanner != null) {
        scanner.close();
      }
      if (out != null) {
        out.close();
      }
    }
  }
}

class Fraction {
  private long numerator;
  private long denominator;

  Fraction(long numerator, long denominator) {
    this.numerator = numerator;
    this.denominator = denominator;
    this.simplify();
  }

  Fraction() {}
  
  void copy(long numerator, long denominator) {
    this.numerator = numerator;
    this.denominator = denominator;
    this.simplify();
  }
  
  void copy(Fraction other) {
    this.numerator = other.numerator;
    this.denominator = other.denominator;
    this.simplify();
  }
    
  long getNumerator(){
    return numerator;
  }
  
  void add(Fraction other){    
    this.numerator   = numerator*other.denominator+
                       denominator*other.numerator;
    this.denominator = denominator*other.denominator;
    this.simplify();
  }
  
  Fraction multiply(Fraction other)
  {
    return
      new Fraction(numerator*other.numerator, 
                    denominator*other.denominator);    
  }
  
  Fraction multiply(long n){
    return
      new Fraction(numerator*n, denominator);    
  }
  
  private static long gcd(long a, long b) {
    while (b != 0) {
      long r = a % b;
      a = b;
      b = r;
    }
    return a;
  }

  void simplify() throws ArithmeticException {
    long d = gcd(this.numerator, this.denominator);

    // if d==0, ArithmeticException is thrown
    this.numerator /= d;
    this.denominator /= d;
    if (this.denominator < 0) {
      this.denominator *= -1;
      this.numerator *= -1;
    }
  }

  static long lcmDenomin(Fraction fr[], int n) {
    long v[] = new long[n];
    int vLen = 0;
    for (int i = 0; i < n; i++) {
      if (fr[i].numerator != 0)
        v[vLen++] = fr[i].denominator;
    }
    Arrays.sort(v, 0, vLen);

    if (vLen < 1)
      return 1;
    long m = v[vLen - 1];
    int isM = 0;
    while (isM == 0) {
      isM = 1;
      for (int i = 1; i < vLen && isM != 0; i++)
        if (m % v[i] != 0) {
          isM = 0;
          break;
        }
      m++;
    }
    m--;
    return m;
  }
}

*/


