import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.io.IOException;
import java.util.Random;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            DLinearCongruentialGenerator solver = new DLinearCongruentialGenerator();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class DLinearCongruentialGenerator {
        public int log(int x, int y) {
            int ans = 0;
            while (y != 0 && y % x == 0) {
                ans++;
                y /= x;
            }
            return ans;
        }

        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            int limit = (int) 2e6;
            IntegerMultiWayStack primeFactors = Factorization.factorizeRangePrime(limit);
            int[] cnts = new int[limit + 1];
            int[] times = new int[limit + 1];
            int[] xs = new int[n];

            in.populate(xs);
            Randomized.shuffle(xs);
            Arrays.sort(xs);
            SequenceUtils.reverse(xs);
            boolean[] retain = new boolean[n];
            for (int i = 0; i < n; i++) {
                int x = xs[i];
                if (cnts[x] == 0) {
                    retain[i] = true;
                    cnts[x] = 1;
                    times[x] = 1;
                    continue;
                }

                for (IntegerIterator iterator = primeFactors.iterator(x - 1); iterator.hasNext(); ) {
                    int p = iterator.next();
                    int log = log(p, x - 1);
                    if (cnts[p] < log) {
                        cnts[p] = log;
                        times[p] = 0;
                    }
                    if (cnts[p] == log) {
                        times[p]++;
                    }
                }
            }

            Modular mod = new Modular(1e9 + 7);
            int prod = 1;
            for (int i = 1; i <= limit; i++) {
                for (int j = 0; j < cnts[i]; j++) {
                    prod = mod.mul(prod, i);
                }
            }

            for (int i = 0; i < n; i++) {
                int x = xs[i];
                boolean unique = false;
                if (retain[i]) {
                    if (cnts[x] == 1 && times[x] == 1) {
                        unique = true;
                    }
                } else {
                    for (IntegerIterator iterator = primeFactors.iterator(x - 1); iterator.hasNext(); ) {
                        int p = iterator.next();
                        int log = log(p, x - 1);
                        if (cnts[p] == log && times[p] == 1) {
                            unique = true;
                        }
                    }
                }
                if (!unique) {
                    prod = mod.plus(prod, 1);
                    break;
                }
            }

            out.println(prod);
        }

    }

    static class Modular {
        int m;

        public Modular(int m) {
            this.m = m;
        }

        public Modular(long m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public Modular(double m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public int valueOf(int x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return x;
        }

        public int valueOf(long x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return (int) x;
        }

        public int mul(int x, int y) {
            return valueOf((long) x * y);
        }

        public int plus(int x, int y) {
            return valueOf(x + y);
        }

        public String toString() {
            return "mod " + m;
        }

    }

    static class DigitUtils {
        private DigitUtils() {
        }

        public static boolean isMultiplicationOverflow(long a, long b, long limit) {
            if (limit < 0) {
                limit = -limit;
            }
            if (a < 0) {
                a = -a;
            }
            if (b < 0) {
                b = -b;
            }
            if (a == 0 || b == 0) {
                return false;
            }
            //a * b > limit => a > limit / b
            return a > limit / b;
        }

    }

    static class RandomWrapper {
        private Random random;
        public static RandomWrapper INSTANCE = new RandomWrapper(new Random());

        public RandomWrapper() {
            this(new Random());
        }

        public RandomWrapper(Random random) {
            this.random = random;
        }

        public int nextInt(int l, int r) {
            return random.nextInt(r - l + 1) + l;
        }

    }

    static class Randomized {
        public static void shuffle(int[] data) {
            shuffle(data, 0, data.length - 1);
        }

        public static void shuffle(int[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                int tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static int nextInt(int l, int r) {
            return RandomWrapper.INSTANCE.nextInt(l, r);
        }

    }

    static class MinimumNumberWithMaximumFactors {
        private static int[] primes = new int[]{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};

        public static long[] maximumPrimeFactor(long n) {
            long[] ans = new long[2];
            ans[0] = 1;
            for (int i = 0; i < primes.length; i++) {
                if (DigitUtils.isMultiplicationOverflow(ans[0], primes[i], n)) {
                    break;
                }
                ans[0] *= primes[i];
                ans[1]++;
            }
            return ans;
        }

    }

    static class IntegerMultiWayStack {
        private int[] values;
        private int[] next;
        private int[] heads;
        private int alloc;
        private int stackNum;

        public IntegerIterator iterator(final int queue) {
            return new IntegerIterator() {
                int ele = heads[queue];

                public boolean hasNext() {
                    return ele != 0;
                }

                public int next() {
                    int ans = values[ele];
                    ele = next[ele];
                    return ans;
                }
            };
        }

        private void doubleCapacity() {
            int newSize = Math.max(next.length + 10, next.length * 2);
            next = Arrays.copyOf(next, newSize);
            values = Arrays.copyOf(values, newSize);
        }

        public void alloc() {
            alloc++;
            if (alloc >= next.length) {
                doubleCapacity();
            }
            next[alloc] = 0;
        }

        public boolean isEmpty(int qId) {
            return heads[qId] == 0;
        }

        public IntegerMultiWayStack(int qNum, int totalCapacity) {
            values = new int[totalCapacity + 1];
            next = new int[totalCapacity + 1];
            heads = new int[qNum];
            stackNum = qNum;
        }

        public void addLast(int qId, int x) {
            alloc();
            values[alloc] = x;
            next[alloc] = heads[qId];
            heads[qId] = alloc;
        }

        public String toString() {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < stackNum; i++) {
                if (isEmpty(i)) {
                    continue;
                }
                builder.append(i).append(": ");
                for (IntegerIterator iterator = iterator(i); iterator.hasNext(); ) {
                    builder.append(iterator.next()).append(",");
                }
                if (builder.charAt(builder.length() - 1) == ',') {
                    builder.setLength(builder.length() - 1);
                }
                builder.append('\n');
            }
            return builder.toString();
        }

    }

    static class Factorization {
        public static IntegerMultiWayStack factorizeRangePrime(int n) {
            int maxFactorCnt = (int) MinimumNumberWithMaximumFactors.maximumPrimeFactor(n)[1];
            IntegerMultiWayStack stack = new IntegerMultiWayStack(n + 1, n * maxFactorCnt);
            boolean[] isComp = new boolean[n + 1];
            for (int i = 2; i <= n; i++) {
                if (isComp[i]) {
                    continue;
                }
                for (int j = i; j <= n; j += i) {
                    isComp[j] = true;
                    stack.addLast(j, i);
                }
            }
            return stack;
        }

    }

    static class FastOutput implements AutoCloseable, Closeable, Appendable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput append(CharSequence csq) {
            cache.append(csq);
            return this;
        }

        public FastOutput append(CharSequence csq, int start, int end) {
            cache.append(csq, start, end);
            return this;
        }

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput append(char c) {
            cache.append(c);
            return this;
        }

        public FastOutput append(int c) {
            cache.append(c);
            return this;
        }

        public FastOutput println(int c) {
            return append(c).println();
        }

        public FastOutput println() {
            cache.append(System.lineSeparator());
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class SequenceUtils {
        public static void swap(int[] data, int i, int j) {
            int tmp = data[i];
            data[i] = data[j];
            data[j] = tmp;
        }

        public static void reverse(int[] data, int l, int r) {
            while (l < r) {
                swap(data, l, r);
                l++;
                r--;
            }
        }

        public static void reverse(int[] data) {
            reverse(data, 0, data.length - 1);
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        public void populate(int[] data) {
            for (int i = 0; i < data.length; i++) {
                data[i] = readInt();
            }
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }

    static interface IntegerIterator {
        boolean hasNext();

        int next();

    }
}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.NoSuchElementException;

public class C {

  private void solve(FastScanner in, PrintWriter out) {
    int MAX = 50;

    // count[i] := 2^i の数
    int[] count = new int[MAX + 1];

    // garbage[i] := 2^(i+1) 以下の garbage の数
    int[] garbage = new int[MAX + 1];

    int N = in.nextInt();
    for (int i = 0; i < N; i++) {
      long z = in.nextLong();
      if (Long.bitCount(z) == 1) {
        //2べきのものはカウントする
        count[Long.numberOfTrailingZeros(z)]++;
      } else {
        long floor = Long.highestOneBit(z);
        garbage[Long.numberOfTrailingZeros(floor)]++;
      }
    }

    for (int bit = 0; bit < MAX; bit++) {
      if (count[bit] < count[bit + 1]) {
        garbage[bit] += count[bit + 1] - count[bit];
        count[bit + 1] = count[bit];
      }
    }

    ArrayList<Integer> answers = new ArrayList<>();
    for (int ans = 1; ans <= N; ans++) {
      if (count[0] < ans) {
        continue;
      }

      int currentGarbage = 0;
      for (int bit = 0; bit < MAX; bit++) {
        //今建っている整数
        int now = Math.min(count[bit], ans);
        //まだ高さがある整数
        int next = Math.min(count[bit + 1], ans);

        // ここで garbageを吸着できる整数
        int catching = now - next;

        //新たに生まれた garbage
        int newGarbage = Math.max(0, count[bit] - ans);

        currentGarbage += garbage[bit] + newGarbage - catching;
        if (currentGarbage < 0) {
          currentGarbage = 0;
        }
      }

      if (currentGarbage == 0) {
        answers.add(ans);
      }
    }

    if (answers.isEmpty()) {
      out.println(-1);
      return;
    }
    for (int a : answers) {
      out.print(a + " ");
    }
    out.println();
  }

  public static void main(String[] args) {
    PrintWriter out = new PrintWriter(System.out);
    new C().solve(new FastScanner(), out);
    out.close();
  }

  private static class FastScanner {

    private final InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int bufferLength = 0;

    private boolean hasNextByte() {
      if (ptr < bufferLength) {
        return true;
      } else {
        ptr = 0;
        try {
          bufferLength = in.read(buffer);
        } catch (IOException e) {
          e.printStackTrace();
        }
        if (bufferLength <= 0) {
          return false;
        }
      }
      return true;
    }

    private int readByte() {
      if (hasNextByte()) {
        return buffer[ptr++];
      } else {
        return -1;
      }
    }

    private static boolean isPrintableChar(int c) {
      return 33 <= c && c <= 126;
    }

    private void skipUnprintable() {
      while (hasNextByte() && !isPrintableChar(buffer[ptr])) {
        ptr++;
      }
    }

    boolean hasNext() {
      skipUnprintable();
      return hasNextByte();
    }

    public String next() {
      if (!hasNext()) {
        throw new NoSuchElementException();
      }
      StringBuilder sb = new StringBuilder();
      int b = readByte();
      while (isPrintableChar(b)) {
        sb.appendCodePoint(b);
        b = readByte();
      }
      return sb.toString();
    }

    long nextLong() {
      if (!hasNext()) {
        throw new NoSuchElementException();
      }
      long n = 0;
      boolean minus = false;
      int b = readByte();
      if (b == '-') {
        minus = true;
        b = readByte();
      }
      if (b < '0' || '9' < b) {
        throw new NumberFormatException();
      }
      while (true) {
        if ('0' <= b && b <= '9') {
          n *= 10;
          n += b - '0';
        } else if (b == -1 || !isPrintableChar(b)) {
          return minus ? -n : n;
        } else {
          throw new NumberFormatException();
        }
        b = readByte();
      }
    }

    double nextDouble() {
      return Double.parseDouble(next());
    }

    double[] nextDoubleArray(int n) {
      double[] array = new double[n];
      for (int i = 0; i < n; i++) {
        array[i] = nextDouble();
      }
      return array;
    }

    double[][] nextDoubleMap(int n, int m) {
      double[][] map = new double[n][];
      for (int i = 0; i < n; i++) {
        map[i] = nextDoubleArray(m);
      }
      return map;
    }

    public int nextInt() {
      return (int) nextLong();
    }

    public int[] nextIntArray(int n) {
      int[] array = new int[n];
      for (int i = 0; i < n; i++) {
        array[i] = nextInt();
      }
      return array;
    }

    public long[] nextLongArray(int n) {
      long[] array = new long[n];
      for (int i = 0; i < n; i++) {
        array[i] = nextLong();
      }
      return array;
    }

    public String[] nextStringArray(int n) {
      String[] array = new String[n];
      for (int i = 0; i < n; i++) {
        array[i] = next();
      }
      return array;
    }

    public char[][] nextCharMap(int n) {
      char[][] array = new char[n][];
      for (int i = 0; i < n; i++) {
        array[i] = next().toCharArray();
      }
      return array;
    }

    public int[][] nextIntMap(int n, int m) {
      int[][] map = new int[n][];
      for (int i = 0; i < n; i++) {
        map[i] = nextIntArray(m);
      }
      return map;
    }
  }
}


import java.util.*;
import java.io.*;

public class C {
  FastScanner in;
  PrintWriter out;

  public void solve() throws IOException {
    int[] powCnt = new int[63];
    int[] other = new int[63];
    long[] pows = new long[63];
    pows[0] = 1L;
    for (int i = 1; i < 63; i++) {
      pows[i] = pows[i - 1] * 2;
    }

    int n = in.nextInt();
    long[] a = new long[n];

    for (int i = 0; i < n; i++) {
      a[i] = in.nextLong();
      boolean isPow = false;
      for (int j = 0; j < 63; j++) {
        if (a[i] == pows[j]) {
          powCnt[j]++;
          isPow = true;
        }
        if (!isPow && j != 0 && a[i] > pows[j - 1] && a[i] < pows[j]) {
          other[j]++;
        }
      }
    }

    int min = Arrays.stream(other).sum();
    int max = powCnt[0];
    boolean exists = false;
    for (int len = min; len <= max; len++) {
      int tails = 0;
      int cur = len;
      for (int i = 0; i < 62; i++) {
        int oldCur = cur;
        if (powCnt[i] < cur) {
          cur = powCnt[i];
        }
        int ended = oldCur - cur;
        if (tails < ended) {
          tails = 0;
        } else {
          tails -= ended;
        }
        tails += powCnt[i] - cur;
        tails += other[i + 1];
      }
      if (tails == 0) {
        out.print(len + " ");
        exists = true;
      }
    }
    if (!exists) {
      out.println(-1);
    } else {
      out.println();
    }
  }

  public void run() {
    try {
      in = new FastScanner(System.in);
      out = new PrintWriter(System.out);
      solve();

      out.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  class FastScanner {
    BufferedReader br;
    StringTokenizer st;

    FastScanner(InputStream is) {
      br = new BufferedReader(new InputStreamReader(is));
    }

    String next() {
      while (st == null || !st.hasMoreTokens()) {
        try {
          st = new StringTokenizer(br.readLine());
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
      return st.nextToken();
    }

    int nextInt() {
      return Integer.parseInt(next());
    }

    long nextLong() {
      return Long.parseLong(next());
    }
  }

  public static void main(String[] arg) {
    new C().run();
  }
}


import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;

public class Main {

    public static void main(String[] args) throws IOException {

        Scanner sc = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int n = sc .nextInt();
        long[] a = new long[n];
        for(int i = 0; i < n; ++i)
            a[i] = sc.nextLong();
        ArrayList<Long> b = new ArrayList<>();
        ArrayList<Long> c = new ArrayList<>();
        ArrayList<Integer> d = new ArrayList<>();
        int idx = 0;
        long curPower = 1;
        boolean possible = true;
        for(long x: a)
            if (x == 1) {
                b.add(1l);
                d.add(1);
            } else if ((x & x - 1) == 0) {
                if (x != curPower) {
                    if (curPower * 2 != x) {
                        possible = false;
                        break;
                    }
                    curPower = x;
                    idx = 0;
                }
                if (idx < b.size() && b.get(idx) * 2 == x) {
                    b.set(idx, x);
                    d.set(idx, d.get(idx) + 1);
                    ++idx;
                }
                else
                    c.add(x);
            } else {
                c.add(x);
            }
        int open = b.size();
        possible &= b.size() >= c.size();
        if(possible) for(int i = c.size() - 1, j = 0; i >= 0; --i, ++j) {
            if(c.get(i) <= 2 * b.get(j)) --open;
            else {
                possible = false;
                break;
            }
        }
        ArrayList<Integer> ans = new ArrayList<>();
        if (possible) {
            ans.add(b.size());
            int free = 0;
            for(int i = b.size() - 1; i >= 0; --i) {
                open--;
                free += d.get(i);
                if (open >= free)
                    ans.add(i);
                else
                    break;
            }
            Collections.reverse(ans);
            for(int x: ans)
                out.print(x + " ");
        } else {
            out.println(-1);
        }
        out.close();
    }

    static class Scanner
    {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

        public String next() throws IOException
        {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {return Integer.parseInt(next());}

        public long nextLong() throws IOException {return Long.parseLong(next());}

        public String nextLine() throws IOException {return br.readLine();}

        public boolean ready() throws IOException {return br.ready();}

    }
}


import java.util.Arrays;
import java.util.Scanner;

public class C {
    static int MOD = 1000000007;
    static long MODSQR = MOD * 1L * MOD;

    public static int[][] mul(int[][] a, int[][] b) {
        int[][] result = new int[a.length][b[0].length];
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < b[0].length; j++) {
                long res = 0;
                for (int k = 0; k < a[0].length; k++) {
                    res = (res + a[i][k] * 1L * b[k][j]);
                    if (res > MODSQR)
                        res %= MOD;
                }
                result[i][j] = (int) (res % MOD);
            }
        }
        return result;
    }

    public static int[][] matpow(int[][] base, long exp) {
        int[][] result = new int[base.length][base.length];
        for (int i = 0; i < base.length; i++)
            result[i][i] = 1;
        while (exp > 0) {
            if ((exp & 1) != 0)
                result = mul(result, base);
            base = mul(base, base);
            exp >>= 1;
        }
        return result;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        long n = in.nextLong();
        int k = in.nextInt();
        int[][] C = new int[k + 1][k + 1];
        C[0][0] = 1;
        for (int i = 1; i <= k; i++) {
            C[i][0] = 1;
            for (int j = 1; j <= k; j++)
                C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
        }
        int[][] matrix = new int[2 * k + 3][2 * k + 3];
        for (int i = 0; i <= k; i++) {
            for (int j = 0; j <= i; j++) {
                matrix[i][j] = C[i][j];
                matrix[i][k + j + 1] = C[i][j];
            }
        }
        for (int i = k + 1; i <= 2 * k + 1; i++) {
            int left = i - k - 1;
            for (int j = 0; j <= left; j++) {
                matrix[i][j] = C[left][j];
            }
        }
        matrix[2 * k + 2][2 * k + 2] = 1;
        matrix[2 * k + 2][k] = 1;
        // for (long[] a : matrix)
        // System.out.println(Arrays.toString(a));
        int[][] columnMatrix = new int[2 * k + 3][1];
        for (int i = 0; i < 2 * k + 2; i++)
            columnMatrix[i][0] = 1;
        matrix = matpow(matrix, n);

        columnMatrix = mul(matrix, columnMatrix);
        // for (long[] a : columnMatrix)
        // System.out.println(Arrays.toString(a));
        System.out.println(columnMatrix[2 * k + 2][0]);
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.InputMismatchException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author George Marcus
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskC solver = new TaskC();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskC {
    private static final int MOD = 1000000007;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        long N = in.nextLong();
        int K = in.nextInt();

        int[][] comb = new int[K + 1][K + 1];
        comb[0][0] = 1;
        for(int i = 1; i <= K; i++) {
            comb[i][0] = comb[i][i] = 1;
            for(int j = 1; j < i; j++) {
                comb[i][j] = comb[i - 1][j - 1] + comb[i - 1][j];
                if(comb[i][j] >= MOD)
                    comb[i][j] -= MOD;
            }
        }

        int[][] A = new int[2 * K + 3][2 * K + 3];
        for(int k = 0; k <= K; k++) {
            for(int i = 0; i <= k; i++)
                A[i][k] = comb[k][k - i];
            for(int i = K + 1; i <= K + 1 + k; i++)
                A[i][k] = (int) (comb[k][k - (i - (K + 1))] * (1L << (k - (i - (K + 1)))) % MOD);
        }
        for(int k = K + 1; k <= 2 * K + 1; k++)
            A[k - (K + 1)][k] = 1;
        for(int i = 0; i <= 2 * K + 1; i++)
            A[i][2 * K + 2] = A[i][K];
        A[2 * K + 2][2 * K + 2] = 1;

        int[][] R = fastPow(A, N - 1);

        long ans = 0;
        for(int i = 0; i <= K + 1; i++) {
            ans += R[i][2 * K + 2];
        }
        ans += R[2 * K + 2][2 * K + 2];
        ans %= MOD;

        out.println(ans);
    }

    private int[][] fastPow(int[][] A, long P) {
        int[][] R = new int[A.length][A.length];
        for(int i = 0; i < R.length; i++)
            R[i][i] = 1;

        while(P > 0) {
            if((P & 1) > 0)
                R = mult(R, A);
            A = mult(A, A);
            P >>= 1;
        }

        return R;
    }

    private int[][] mult(int[][] A, int[][] B) {
        int n = A.length;
        int[][] C = new int[n][n];
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++) {
                long crt = 0;
                for(int k = 0; k < n; k++) {
                    crt += (long)A[i][k] * B[k][j];
                    if(crt > 1e16)
                        crt %= MOD;
                }
                crt %= MOD;
                C[i][j] = (int) crt;
            }
        return C;
    }
}

class InputReader {
    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;

    public InputReader(InputStream stream) {
        this.stream = stream;
    }

    public int read() {
        if (numChars == -1)
            throw new InputMismatchException();
        if (curChar >= numChars) {
            curChar = 0;
            try {
                numChars = stream.read(buf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (numChars <= 0)
                return -1;
        }
        return buf[curChar++];
    }

    public int nextInt() {
        return Integer.parseInt(nextString());
    }

    public long nextLong() {
        return Long.parseLong(nextString());
    }

    public String nextString() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        StringBuffer res = new StringBuffer();
        do {
            res.appendCodePoint(c);
            c = read();
        } while (!isSpaceChar(c));

        return res.toString();
    }

    private boolean isSpaceChar(int c) {
        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    }


import java.lang.*;
import java.math.*;
import java.util.*;
import java.io.*;

public class Main {

   void solve(){
       long n=nl();
        int k=ni();
        if(n==1){
            pw.println("1");
            return;
        }
        precompute(k+2);
        sz=k+1+k+1+1;
        long Mat[][]=new long[sz][sz];
        for(int i=0;i<=k;i++){
            Mat[k+1+i][i]=1;
        }
        for(int c=0;c<=k;c++){
            for(int r=0;r<=c;r++){
                Mat[r][k+1+c]=mul(ncr(c,r),pow[c-r],M);
                Mat[k+1+r][k+1+c]=ncr(c,r);
            }
        }
        for(int i=0;i<=2*k+1;i++) Mat[i][2*k+2]=Mat[i][2*k+1];
        Mat[sz-1][sz-1]=1;

        Mat=pow(Mat,n-2);
        long arr[]=new long[sz];
        for(int i=0;i<=k;i++) arr[i]=1;
        for(int i=k+1;i<=2*k+1;i++) arr[i]=pow[i-k];
        arr[sz-1]=1;
        arr[sz-1]=add(arr[sz-1],pow[k+1],M);
//        for(int i=0;i<sz;i++){
//            for(int j=0;j<sz;j++) pw.print(Mat[i][j]+" ");
//            pw.println("");
//        }
        long ans=0;
        for(int i=0;i<sz;i++){
            ans=add(ans,mul(arr[i],Mat[i][sz-1],M),M);
        }
        pw.println(ans);

    }
    int sz;
    long [][] pow(long A[][],long x){
        if(x==0){
            long C[][]=new long[sz][sz];
            for(int i=0;i<sz;i++) C[i][i]=1;
            return C;
        }else if(x==1){
            return A;
        }
        long C[][]=pow(A,x/2);
        C=mul(C,C);
        if((x&1)>0) return mul(A,C);
        return C;

    }
    long [][] mul(long A[][],long B[][]){
        long C[][]=new long[sz][sz];
        for(int i=0;i<sz;i++){
            for(int j=0;j<sz;j++){
                for(int k=0;k<sz;k++){
                    //C[i][j]=(C[i][j]+(A[i][k]%M * B[k][j]%M)%M)%M;
                    C[i][j]=add(C[i][j],mul(A[i][k],B[k][j],M),M);
                }
            }
        }
        return C;
    }

    long ncr(int n,int r) {
        long ans = fact[n];
        ans=mul(ans,inv[n-r],M);
        ans=mul(ans,inv[r],M);
        return ans;
    }
    long fact[];
    long inv[];
    long pow[];
    void precompute(int n){
       fact=new long[n+1];
       inv=new long[n+1];
       pow=new long[n+1];
       pow[0]=1;
       fact[0]=1;
       for(int i=1;i<=n;i++){
           pow[i]=(pow[i-1]*2)%M;
           fact[i]=(fact[i-1]*i)%M;
       }
       inv[n]=modInverse(fact[n],M);
        for(int i=n-1;i>=0;i--) inv[i]=(inv[i+1]*(i+1))%M;

    }
    long add(long x,long y,long M){
        x+=y;
        if(x>=M) x-=M;
        return x;
    }
    long sub(long x,long y,long M){
        x-=y;
        if(x<0) x+=M;
        return x;
    }
    long mul(long x,long y,long M){
        x*=y;
        if(x>=M) x%=M;
        return x;
    }
    long modpow(long a, long b,long M)
    {
        long r=1;
        while(b>0)
        {
            if((b&1)>0) r=mul(r,a,M);
            a=mul(a,a,M);
            b>>=1;
        }
        return r;
    }

    long modInverse(long A, long M)
    {

        return modpow(A,M-2,M);
    }

    long M= (long)1e9+7;
    InputStream is;
    PrintWriter pw;
    String INPUT = "";
    void run() throws Exception {
        is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
        pw = new PrintWriter(System.out);
        long s = System.currentTimeMillis();
        solve();
        pw.flush();
        if(!INPUT.isEmpty())tr(System.currentTimeMillis()-s+"ms");

    }
    public static void main(String[] args) throws Exception { new Main().run(); }

    private byte[] inbuf = new byte[1024];
    public int lenbuf = 0, ptrbuf = 0;

    private int readByte() {
        if(lenbuf == -1)throw new InputMismatchException();
        if(ptrbuf >= lenbuf){
            ptrbuf = 0;
            try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
            if(lenbuf <= 0)return -1;
        }
        return inbuf[ptrbuf++];
    }

    private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
    private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

    private double nd() { return Double.parseDouble(ns()); }
    private char nc() { return (char)skip(); }

    private String ns() {
        int b = skip();
        StringBuilder sb = new StringBuilder();
        while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }

    private char[] ns(int n) {
        char[] buf = new char[n];
        int b = skip(), p = 0;
        while(p < n && !(isSpaceChar(b))){
            buf[p++] = (char)b;
            b = readByte();
        }
        return n == p ? buf : Arrays.copyOf(buf, p);
    }

    private char[][] nm(int n, int m) {
        char[][] map = new char[n][];
        for(int i = 0;i < n;i++)map[i] = ns(m);
        return map;
    }

    private int[] na(int n) {
        int[] a = new int[n];
        for(int i = 0;i < n;i++)a[i] = ni();
        return a;
    }

    private int ni() {
        int num = 0, b;
        boolean minus = false;
        while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if(b == '-'){
            minus = true;
            b = readByte();
        }

        while(true){
            if(b >= '0' && b <= '9'){
                num = num * 10 + (b - '0');
            }else{
                return minus ? -num : num;
            }
            b = readByte();
        }
    }

    private long nl() {
        long num = 0;
        int b;
        boolean minus = false;
        while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
        if(b == '-'){
            minus = true;
            b = readByte();
        }

        while(true){
            if(b >= '0' && b <= '9'){
                num = num * 10 + (b - '0');
            }else{
                return minus ? -num : num;
            }
            b = readByte();
        }
    }
    private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
    private void tr(Object... o) { if(INPUT.length() > 0)System.out.println(Arrays.deepToString(o)); }

}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Deque;
import java.util.function.Supplier;
import java.io.OutputStreamWriter;
import java.io.OutputStream;
import java.util.Collection;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.function.Consumer;
import java.io.Closeable;
import java.io.Writer;
import java.util.ArrayDeque;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            CYetAnotherNumberSequence solver = new CYetAnotherNumberSequence();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class CYetAnotherNumberSequence {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            long n = in.readLong();
            int k = in.readInt();

            Modular mod = new Modular(1000000007);
            Power power = new Power(mod);

            int items = 200;
            int[] fib = new int[items];
            fib[0] = 1;
            fib[1] = 2;
            int[] a = new int[items];
            for (int i = 2; i < items; i++) {
                fib[i] = mod.plus(fib[i - 1], fib[i - 2]);
            }
            for (int i = 0; i < items; i++) {
                a[i] = mod.mul(fib[i], power.pow(i + 1, k));
                if (i > 0) {
                    a[i] = mod.plus(a[i], a[i - 1]);
                }
            }

            IntegerList seq = new IntegerList();
            seq.addAll(a);
            LinearRecurrenceSolver solver = LinearRecurrenceSolver.newSolverFromSequence(seq, mod);
            int ans = solver.solve(n - 1, seq);

            out.println(ans);
        }

    }

    static class Modular {
        int m;

        public int getMod() {
            return m;
        }

        public Modular(int m) {
            this.m = m;
        }

        public Modular(long m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public Modular(double m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public int valueOf(int x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return x;
        }

        public int valueOf(long x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return (int) x;
        }

        public int mul(int x, int y) {
            return valueOf((long) x * y);
        }

        public int plus(int x, int y) {
            return valueOf(x + y);
        }

        public int subtract(int x, int y) {
            return valueOf(x - y);
        }

        public String toString() {
            return "mod " + m;
        }

    }

    static class IntegerList implements Cloneable {
        private int size;
        private int cap;
        private int[] data;
        private static final int[] EMPTY = new int[0];

        public int[] getData() {
            return data;
        }

        public IntegerList(int cap) {
            this.cap = cap;
            if (cap == 0) {
                data = EMPTY;
            } else {
                data = new int[cap];
            }
        }

        public IntegerList(IntegerList list) {
            this.size = list.size;
            this.cap = list.cap;
            this.data = Arrays.copyOf(list.data, size);
        }

        public IntegerList() {
            this(0);
        }

        public void ensureSpace(int req) {
            if (req > cap) {
                while (cap < req) {
                    cap = Math.max(cap + 10, 2 * cap);
                }
                data = Arrays.copyOf(data, cap);
            }
        }

        private void checkRange(int i) {
            if (i < 0 || i >= size) {
                throw new ArrayIndexOutOfBoundsException("index " + i + " out of range");
            }
        }

        public int get(int i) {
            checkRange(i);
            return data[i];
        }

        public void add(int x) {
            ensureSpace(size + 1);
            data[size++] = x;
        }

        public void addAll(int[] x) {
            addAll(x, 0, x.length);
        }

        public void addAll(int[] x, int offset, int len) {
            ensureSpace(size + len);
            System.arraycopy(x, offset, data, size, len);
            size += len;
        }

        public void addAll(IntegerList list) {
            addAll(list.data, 0, list.size);
        }

        public void expandWith(int x, int len) {
            ensureSpace(len);
            while (size < len) {
                data[size++] = x;
            }
        }

        public void retain(int n) {
            if (n < 0) {
                throw new IllegalArgumentException();
            }
            if (n >= size) {
                return;
            }
            size = n;
        }

        public void set(int i, int x) {
            checkRange(i);
            data[i] = x;
        }

        public int size() {
            return size;
        }

        public int[] toArray() {
            return Arrays.copyOf(data, size);
        }

        public void clear() {
            size = 0;
        }

        public String toString() {
            return Arrays.toString(toArray());
        }

        public boolean equals(Object obj) {
            if (!(obj instanceof IntegerList)) {
                return false;
            }
            IntegerList other = (IntegerList) obj;
            return SequenceUtils.equal(data, 0, size - 1, other.data, 0, other.size - 1);
        }

        public int hashCode() {
            int h = 1;
            for (int i = 0; i < size; i++) {
                h = h * 31 + Integer.hashCode(data[i]);
            }
            return h;
        }

        public IntegerList clone() {
            IntegerList ans = new IntegerList();
            ans.addAll(this);
            return ans;
        }

    }

    static class SequenceUtils {
        public static boolean equal(int[] a, int al, int ar, int[] b, int bl, int br) {
            if ((ar - al) != (br - bl)) {
                return false;
            }
            for (int i = al, j = bl; i <= ar; i++, j++) {
                if (a[i] != b[j]) {
                    return false;
                }
            }
            return true;
        }

    }

    static class ModLinearFeedbackShiftRegister {
        private IntegerList cm;
        int m = -1;
        int dm;
        private IntegerList cn;
        private IntegerList buf;
        private IntegerList seq;
        private Modular mod;
        private Power pow;

        public ModLinearFeedbackShiftRegister(Modular mod, int cap) {
            cm = new IntegerList(cap + 1);
            cn = new IntegerList(cap + 1);
            seq = new IntegerList(cap + 1);
            buf = new IntegerList(cap + 1);
            cn.add(1);

            this.mod = mod;
            this.pow = new Power(mod);
        }

        public ModLinearFeedbackShiftRegister(Modular mod) {
            this(mod, 0);
        }

        private int estimateDelta() {
            int n = seq.size() - 1;
            int ans = 0;
            int[] cnData = cn.getData();
            int[] seqData = seq.getData();
            for (int i = 0, until = cn.size(); i < until; i++) {
                ans = mod.plus(ans, mod.mul(cnData[i], seqData[n - i]));
            }
            return ans;
        }

        public void add(int x) {
            x = mod.valueOf(x);
            int n = seq.size();

            seq.add(x);
            int dn = estimateDelta();
            if (dn == 0) {
                return;
            }

            if (m < 0) {
                cm.clear();
                cm.addAll(cn);
                dm = dn;
                m = n;

                cn.expandWith(0, n + 2);
                return;
            }

            int ln = cn.size() - 1;
            int len = Math.max(ln, n + 1 - ln);
            buf.clear();
            buf.addAll(cn);
            buf.expandWith(0, len + 1);

            int factor = mod.mul(dn, pow.inverseByFermat(dm));

            int[] bufData = buf.getData();
            int[] cmData = cm.getData();
            for (int i = n - m, until = n - m + cm.size(); i < until; i++) {
                bufData[i] = mod.subtract(bufData[i], mod.mul(factor, cmData[i - (n - m)]));
            }

            if (cn.size() < buf.size()) {
                IntegerList tmp = cm;
                cm = cn;
                cn = tmp;
                m = n;
                dm = dn;
            }
            {
                IntegerList tmp = cn;
                cn = buf;
                buf = tmp;
            }

        }

        public int length() {
            return cn.size() - 1;
        }

        public String toString() {
            return cn.toString();
        }

        public int codeAt(int i) {
            return mod.valueOf(-cn.get(i));
        }

    }

    static class Buffer<T> {
        private Deque<T> deque;
        private Supplier<T> supplier;
        private Consumer<T> cleaner;

        public Buffer(Supplier<T> supplier) {
            this(supplier, (x) -> {
            });
        }

        public Buffer(Supplier<T> supplier, Consumer<T> cleaner) {
            this(supplier, cleaner, 0);
        }

        public Buffer(Supplier<T> supplier, Consumer<T> cleaner, int exp) {
            this.supplier = supplier;
            this.cleaner = cleaner;
            deque = new ArrayDeque<>(exp);
        }

        public T alloc() {
            return deque.isEmpty() ? supplier.get() : deque.removeFirst();
        }

        public void release(T e) {
            cleaner.accept(e);
            deque.addLast(e);
        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(int c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class LinearRecurrenceSolver {
        Modular mod;
        IntegerList coe;
        IntegerList p;
        IntegerList remainder;
        Power pow;
        int n;

        private LinearRecurrenceSolver(IntegerList coe, Modular mod) {
            this.coe = coe;
            this.mod = mod;
            n = coe.size();
            pow = new Power(mod);
            remainder = new IntegerList(coe.size());
            p = new IntegerList(coe.size() + 1);
            for (int i = n - 1; i >= 0; i--) {
                p.add(mod.valueOf(-coe.get(i)));
            }
            p.add(1);
        }

        public static LinearRecurrenceSolver newSolverFromLinearRecurrence(IntegerList coe, Modular mod) {
            return new LinearRecurrenceSolver(coe, mod);
        }

        public static LinearRecurrenceSolver newSolverFromSequence(IntegerList seq, Modular mod) {
            ModLinearFeedbackShiftRegister lfsr = new ModLinearFeedbackShiftRegister(mod, seq.size());
            for (int i = 0; i < seq.size(); i++) {
                lfsr.add(seq.get(i));
            }
            IntegerList coes = new IntegerList(lfsr.length());
            for (int i = 1; i <= lfsr.length(); i++) {
                coes.add(lfsr.codeAt(i));
            }
            return newSolverFromLinearRecurrence(coes, mod);
        }

        private int solve(IntegerList a) {
            int ans = 0;
            remainder.expandWith(0, n);
            for (int i = 0; i < n; i++) {
                ans = mod.plus(ans, mod.mul(remainder.get(i), a.get(i)));
            }
            return ans;
        }

        public int solve(long k, IntegerList a) {
            if (k < a.size()) {
                return a.get((int) k);
            }
            Polynomials.module(k, p, remainder, pow);
            return solve(a);
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public long readLong() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            long val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }

    static class ExtGCD {
        private long x;
        private long y;
        private long g;

        public long getX() {
            return x;
        }

        public long extgcd(long a, long b) {
            if (a >= b) {
                g = extgcd0(a, b);
            } else {
                g = extgcd0(b, a);
                long tmp = x;
                x = y;
                y = tmp;
            }
            return g;
        }

        private long extgcd0(long a, long b) {
            if (b == 0) {
                x = 1;
                y = 0;
                return a;
            }
            long g = extgcd0(b, a % b);
            long n = x;
            long m = y;
            x = m;
            y = n - m * (a / b);
            return g;
        }

    }

    static class Polynomials {
        public static Buffer<IntegerList> listBuffer = new Buffer<>(IntegerList::new, list -> list.clear());
        private static ExtGCD extGCD = new ExtGCD();

        public static int rankOf(IntegerList p) {
            int[] data = p.getData();
            int r = p.size() - 1;
            while (r >= 0 && data[r] == 0) {
                r--;
            }
            return Math.max(0, r);
        }

        public static void normalize(IntegerList list) {
            list.retain(rankOf(list) + 1);
        }

        public static void mul(IntegerList a, IntegerList b, IntegerList c, Modular mod) {
            int rA = rankOf(a);
            int rB = rankOf(b);
            c.clear();
            c.expandWith(0, rA + rB + 1);
            int[] aData = a.getData();
            int[] bData = b.getData();
            int[] cData = c.getData();
            for (int i = 0; i <= rA; i++) {
                for (int j = 0; j <= rB; j++) {
                    cData[i + j] = mod.plus(cData[i + j], mod.mul(aData[i], bData[j]));
                }
            }
        }

        public static void divide(IntegerList a, IntegerList b, IntegerList c, IntegerList remainder, Power pow) {
            Modular mod = pow.getModular();
            int rA = rankOf(a);
            int rB = rankOf(b);

            if (rA < rB) {
                c.clear();
                c.add(0);
                remainder.clear();
                remainder.addAll(a);
                return;
            }

            int rC = Math.max(0, rA - rB);
            c.clear();
            c.expandWith(0, rC + 1);
            remainder.clear();
            remainder.addAll(a);

            int[] bData = b.getData();
            int[] cData = c.getData();
            int[] rData = remainder.getData();

            if (extGCD.extgcd(b.get(rB), mod.getMod()) != 1) {
                throw new IllegalArgumentException();
            }
            int inv = mod.valueOf(extGCD.getX());
            for (int i = rA, j = rC; i >= rB; i--, j--) {
                if (rData[i] == 0) {
                    continue;
                }
                int factor = mod.mul(-rData[i], inv);
                cData[j] = mod.valueOf(-factor);
                for (int k = rB; k >= 0; k--) {
                    rData[k + j] = mod.plus(rData[k + j], mod.mul(factor, bData[k]));
                }
            }

            normalize(remainder);
        }

        public static void module(long k, IntegerList p, IntegerList remainder, Power pow) {
            int rP = rankOf(p);
            if (rP == 0) {
                remainder.clear();
                remainder.add(0);
                return;
            }

            IntegerList a = listBuffer.alloc();
            IntegerList c = listBuffer.alloc();

            module(k, a, p, c, remainder, rP, pow);

            listBuffer.release(a);
            listBuffer.release(c);
        }

        private static void module(long k, IntegerList a, IntegerList b, IntegerList c, IntegerList remainder, int rb, Power pow) {
            Modular mod = pow.getModular();
            if (k < rb) {
                remainder.clear();
                remainder.expandWith(0, (int) k + 1);
                remainder.set((int) k, 1);
                return;
            }
            module(k / 2, a, b, c, remainder, rb, pow);
            mul(remainder, remainder, a, mod);
            if (k % 2 == 1) {
                int ra = rankOf(a);
                a.expandWith(0, ra + 2);
                int[] aData = a.getData();
                for (int i = ra; i >= 0; i--) {
                    aData[i + 1] = aData[i];
                }
                aData[0] = 0;
            }
            divide(a, b, c, remainder, pow);
        }

    }

    static class Power {
        final Modular modular;

        public Modular getModular() {
            return modular;
        }

        public Power(Modular modular) {
            this.modular = modular;
        }

        public int pow(int x, int n) {
            if (n == 0) {
                return modular.valueOf(1);
            }
            long r = pow(x, n >> 1);
            r = modular.valueOf(r * r);
            if ((n & 1) == 1) {
                r = modular.valueOf(r * x);
            }
            return (int) r;
        }

        public int inverseByFermat(int x) {
            return pow(x, modular.m - 2);
        }

    }
}


import java.io.*;
import java.lang.reflect.Array;
import java.math.*;
import java.text.DecimalFormat;
import java.util.*;

public class Main {
    public static final int mod = 1000000007;
    private static int [] [] C;
    public static int add(int a,int b) {
        a += b;
        if (a >= mod) a -= mod;
        return a;
    }
    public static int mul(int a,int b){
        return (int)((a*(long)b)%mod);
    }

    private static void init(){
        int MAXK = 40;
        C = new int[MAXK+1][MAXK+1];
        for (int n = 0;n <= MAXK;n++){
            C[n][0] = C[n][n] = 1;
            for (int k = 1;k < n;k++)
                C[n][k] = add(C[n-1][k],C[n-1][k-1]);
        }
    }

    private static matrix buildMatrix(int K){
        matrix ret = new matrix(2*K+3);
        for (int i = 0;i <= K;i++) {
            int r = i+1,k = K - i;
            for (int j = 0;j <= k;j++) {
                int c = r + j;
                ret.A[r][c] = C[k][j];
            }
            for (int j = 0;j <= k;j++) {
                int c = r + j + K + 1;
                ret.A[r][c] = C[k][j];
            }
            for (int j = 1;j <= K+1;j++) {
                int rd = r + K+1;
                ret.A[rd][j] = ret.A[r][j];
            }

        }
        for (int i = 1;i < ret.n;i++)
            ret.A[0][i] = ret.A[1][i];
        ret.A[0][0] = 1;
        return ret;
    }

    private static int powmod(int x,int p) {
        if (p == 0) return 1;
        int y = 1;
        for (;p > 1;p >>= 1) {
            if (p%2 == 1) y = mul(x,y);
            x = mul(x,x);
        }
        return mul(x,y);
    }
    public static void main(String[] args) throws Exception{
        IO io = new IO(null,null);
        init();
        long n = io.getNextLong();
        int K = io.getNextInt();
        int S2 = add(1,powmod(2,K+1));
        if (n == 1)io.println(1);
        else {
            matrix mat = buildMatrix(K);
//            for (int i = 0;i < mat.n;i++)
//                System.err.println(Arrays.toString(mat.A[i]));
//            System.err.println("");
            int [] [] A = mat.exp(n-2);
            int [] B = new int[mat.n];
            B[0] = S2;
            for (int i = 0;i <= K;i++)
                B[i+1] = powmod(2,K-i + 1);
            for (int i = 0;i <= K;i++)
                B[i+K+2] = powmod(2,K-i);
//            for (int i = 0;i < mat.n;i++)
//                System.err.println(Arrays.toString(A[i]));
//            System.err.println("");
//            System.err.println(Arrays.toString(B));

            int [] C = new int[A.length];
            for (int i = 0;i < A.length;i++)
                for (int j = 0;j < A.length;j++)
                    C[i] = add(C[i],mul(A[i][j],B[j]));
//            System.err.println(Arrays.toString(C));
            io.println(C[0]);
        }
        io.close();
    }
}

class matrix{
    int [] [] A;
    int n;
    public matrix(int dim){
        A = new int[dim][dim];
        n = dim;
    }
    public void makeEye(){
        for (int i = 0;i < n;i++)
            for (int j = 0;j < n;j++)
                A[i][j] = (i == j) ? 1 : 0;
    }
    public matrix mul(matrix O) {
        matrix C = new matrix(n);
        for (int i = 0;i < n;i++)
            for (int j = 0;j < n;j++)
                for (int k = 0;k < n;k++)
                    C.A[i][j] = Main.add(C.A[i][j],Main.mul(A[i][k],O.A[k][j]));
        return C;
    }
    public int [] [] exp(long p) {
        matrix B = new matrix(n);
        matrix C = new matrix(n);
        C.makeEye();
        for (int i = 0;i < n;i++)
            for (int j = 0;j < n;j++)
                B.A[i][j] = A[i][j];

        if (p == 0) {
            B.makeEye();
            return B.A;
        }
        for (;p > 1;p >>= 1) {
            if (p%2 == 1) C = C.mul(B);
            B = B.mul(B);
        }
        return B.mul(C).A;
    }
}

class IO{
    private BufferedReader br;
    private StringTokenizer st;
    private PrintWriter writer;
    private String inputFile,outputFile;

    public boolean hasMore() throws IOException{
        if(st != null && st.hasMoreTokens()) return true;
        if(br != null && br.ready()) return true;
        return false;
    }
    public String getNext() throws FileNotFoundException, IOException{
        while(st == null || !st.hasMoreTokens()) st = new StringTokenizer(br.readLine());
        return st.nextToken();
    }

    public String getNextLine() throws FileNotFoundException, IOException{
        return br.readLine().trim();
    }

    public int getNextInt() throws FileNotFoundException, IOException{
        return Integer.parseInt(getNext());
    }
    public long getNextLong() throws FileNotFoundException, IOException{
        return Long.parseLong(getNext());
    }

    public void print(double x,int num_digits) throws  IOException{
        writer.printf("%." + num_digits + "f" ,x);
    }
    public void println(double x,int num_digits) throws  IOException{
        writer.printf("%." + num_digits + "f\n" ,x);
    }
    public void print(Object o) throws  IOException{
        writer.print(o.toString());
    }

    public void println(Object o) throws  IOException{
        writer.println(o.toString());
    }
    public IO(String x,String y) throws FileNotFoundException, IOException{
        inputFile = x;
        outputFile = y;
        if(x != null) br = new BufferedReader(new FileReader(inputFile));
        else br = new BufferedReader(new InputStreamReader(System.in));
        if(y != null) writer = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));
        else writer = new PrintWriter(new OutputStreamWriter(System.out));
    }

    protected void close() throws IOException{
        br.close();
        writer.close();
    }
    public void outputArr(Object [] A) throws IOException{
        int L = A.length;
        for (int i = 0;i < L;i++) {
            if(i > 0) writer.print(" ");
            writer.print(A[i]);
        }
        writer.print("\n");
    }
}


import java.io.*;
import java.util.Arrays;

public class CF392C {

    final static long MOD = 1000000007;

    static long[][] mul(long[][] a, long[][] b) {
        long[][] c = new long[a.length][a.length];
        for (int i = 0; i < a.length; ++i) {
            for (int j = 0; j < a.length; ++j) {
                for (int k = 0; k < a.length; ++k) {
                    c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % MOD;
                }
            }
        }
        return c;
    }

    static long[][] pow(long[][] a, long pow) {
        long[][] r = new long[a.length][a.length];
        for (int i = 0; i < a.length; ++i) {
            r[i][i] = 1;
        }
        while (pow > 0) {
            if (pow % 2 == 1) {
                r = mul(r, a);
            }
            pow /= 2;
            a = mul(a, a);
        }
        return r;
    }

    public static void solve(Input in, PrintWriter out) throws IOException {
        long n = in.nextLong();
        int k = in.nextInt() + 1;
        long[][] cs = new long[k + 1][k + 1];
        for (int i = 0; i < cs.length; ++i) {
            for (int j = 1; j < i; ++j) {
                cs[i][j] = (cs[i - 1][j - 1] + cs[i - 1][j]) % MOD;
            }
            cs[i][0] = cs[i][i] = 1;
        }
        long[][] a = new long[2 * k + 1][2 * k + 1];
        long[][] b = new long[2 * k + 1][2 * k + 1];
        long[][] c = new long[2 * k + 1][2 * k + 1];
        a[2 * k][2 * k] = b[2 * k][2 * k] = c[2 * k][2 * k] = 1;
        a[2 * k][2 * k - 1] = 1;
        for (int i = 0; i < k; ++i) {
            a[k + i][k + i] = 1;
            b[i][k + i] = 1;
            b[k + i][i] = 1;
            b[k + i][k + i] = 1;
            c[i][i] = 1;
            for (int j = 0; j <= i; ++j) {
                a[i][j] = cs[i][j];
                c[k + i][k + j] = cs[i][j];
            }
        }
        long[][] m = mul(c, mul(b, a));
//        long[] r = new long[2 * k + 1];
//        for (int i = 0; i < k; ++i) {
//            r[k + i] = 1;
//        }
//        r[0] = 1;
//        for (int it = 0; it < n; ++it) {
//            System.err.println(Arrays.toString(r));
//            long[] r1 = new long[2 * k + 1];
//            for (int i = 0; i < 2 * k + 1; ++i) {
//                for (int j = 0; j < 2 * k + 1; ++j) {
//                    r1[i] = (r1[i] + m[i][j] * r[j]) % MOD;
//                }
//            }
//            r = r1;
//        }
//        System.err.println(Arrays.toString(r));
        m = pow(m, n);
        long ans = m[2 * k][0];
        for (int i = 0; i < k; ++i) {
            ans = (ans + m[2 * k][k + i]) % MOD;
        }
        out.println(ans);
    }

    public static void main(String[] args) throws IOException {
        PrintWriter out = new PrintWriter(System.out);
        solve(new Input(new BufferedReader(new InputStreamReader(System.in))), out);
        out.close();
    }

    static class Input {
        BufferedReader in;
        StringBuilder sb = new StringBuilder();

        public Input(BufferedReader in) {
            this.in = in;
        }

        public Input(String s) {
            this.in = new BufferedReader(new StringReader(s));
        }

        public String next() throws IOException {
            sb.setLength(0);
            while (true) {
                int c = in.read();
                if (c == -1) {
                    return null;
                }
                if (" \n\r\t".indexOf(c) == -1) {
                    sb.append((char)c);
                    break;
                }
            }
            while (true) {
                int c = in.read();
                if (c == -1 || " \n\r\t".indexOf(c) != -1) {
                    break;
                }
                sb.append((char)c);
            }
            return sb.toString();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }
    }
}


//package round791;
import java.io.*;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.Queue;

public class F2 {
	InputStream is;
	FastWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni();
		boolean[][] g = new boolean[10][10];
		for(int m = ni();m > 0;m--){
			int x = ni(), y = ni();
			g[x][y] = g[y][x] = true;
		}
		for(int i = 0;i < 10;i++)g[i][i] = true;

		int[][] njs = new int[1<<9][10];
		for(int j = 0;j < 1<<9;j++) {
			for (int k = 0; k < 10; k++) {
				if (j << ~k >= 0) {
					int nj = j;
					for (int l = 0; l < 10; l++) {
						if (g[k][l]) {
							if (k > l) {
								nj |= 1 << l;
							}
						} else {
							nj &= ~(1 << l);
						}
					}
					njs[j][k] = nj;
				}
			}
		}

		long[] dp = new long[1<<9];
		dp[0] = 1;
		for(int i = 1;i <= n;i++){
			long[] ndp = new long[1<<9];
			for(int j = 0;j < 1<<9;j++){
				for(int k = 0;k < 10;k++){
					if (j << ~k >= 0) {
						int nj = njs[j][k];
						ndp[nj] += dp[j];
						if(ndp[nj] >= mod)ndp[nj] -= mod;
					}
				}
			}
			dp = ndp;
		}
		long ans = sum(dp) % mod;
		out.println(ans);
	}

	public static long sum(long... a){long ret = 0; for(long v : a)ret += v; return ret;}

	public static final int mod = 998244353;
	public static final int G = 3;

	// only 998244353
	public static long[] mul(long[] a, long[] b)
	{
		if(a.length == 0 && b.length == 0)return new long[0];
		if(a.length + b.length >= 300) {
			return Arrays.copyOf(NTTStockham998244353.convolve(a, b), a.length + b.length - 1);
		}else{
			return mulnaive(a, b);
		}
	}

	public static long[] mul(long[] a, long[] b, int lim)
	{
		if(a.length + b.length >= 300) {
			return Arrays.copyOf(NTTStockham998244353.convolve(a, b), lim);
		}else{
			return mulnaive(a, b, lim);
		}
	}

	//	public static final int mod = 1000000007;
	//	public static long[] mul(long[] a, long[] b)
	//	{
	//		if(Math.max(a.length, b.length) >= 3000){
	//			return Arrays.copyOf(NTTCRT.convolve(a, b, 3, mod), a.length+b.length-1);
	//		}else{
	//			return mulnaive(a, b);
	//		}
	//	}

	//	public static long[] mul(long[] a, long[] b, int lim)
	//	{
	//		if(Math.max(a.length, b.length) >= 3000){
	//			return Arrays.copyOf(NTTCRT.convolve(a, b, 3, mod), lim);
	//		}else{
	//			return mulnaive(a, b, lim);
	//		}
	//	}

	public static final long big = (Long.MAX_VALUE/mod/mod-1)*mod*mod;

	public static long[] mulnaive(long[] a, long[] b)
	{
		long[] c = new long[a.length+b.length-1];
		for(int i = 0;i < a.length;i++){
			for(int j = 0;j < b.length;j++){
				c[i+j] += a[i]*b[j];
				if(c[i+j] >= big)c[i+j] -= big;
			}
		}
		for(int i = 0;i < c.length;i++)c[i] %= mod;
		return c;
	}

	public static long[] mulnaive(long[] a, long[] b, int lim)
	{
		long[] c = new long[lim];
		for(int i = 0;i < a.length;i++){
			for(int j = 0;j < b.length && i+j < lim;j++){
				c[i+j] += a[i]*b[j];
				if(c[i+j] >= big)c[i+j] -= big;
			}
		}
		for(int i = 0;i < c.length;i++)c[i] %= mod;
		return c;
	}

	public static class NTTStockham998244353 {
		private static final int P = 998244353, mod = P, G = 3;
		private static long[] wps;

		public static long[] convolve(long[] a, long[] b)
		{
			int m = Math.max(2, Integer.highestOneBit(Math.max(a.length, b.length)-1)<<2);

			wps = new long[m];
			long unit = pow(G, (P-1)/m);
			wps[0] = 1;
			for(int p = 1;p < m;p++) {
				wps[p] = wps[p-1] * unit % mod;
			}

			long[] fa = go(a, m, false);
			long[] fb = a == b ? fa : go(b, m, false);
			for(int i = 0;i < m;i++){
				fa[i] = fa[i]*fb[i] % mod;
			}
			fa = go(fa, m, true);
			for(int i = 1, j = m-1;i < j;i++,j--) {
				long d = fa[i]; fa[i] = fa[j]; fa[j] = d;
			}
			return fa;
		}

		private static void fft(long[] X, long[] Y)
		{
			int s = 1;
			boolean eo = false;
			for(int n = X.length;n >= 4;n /= 2) {
				int m = n/2;
				for(int p = 0;p < m;p++) {
					long wp = wps[s*p];
					long wk = (wp<<32)/P;
					for(int q = 0;q < s;q++) {
						long a = X[q + s*(p+0)];
						long b = X[q + s*(p+m)];
						long ndsts = a + b;
						if(ndsts >= 2*P)ndsts -= 2*P;
						long T = a - b + 2*P;
						long Q = wk*T>>>32;
						Y[q + s*(2*p+0)] = ndsts;
						Y[q + s*(2*p+1)] = wp*T-Q*P&(1L<<32)-1;
					}
				}
				s *= 2;
				eo = !eo;
				long[] D = X; X = Y; Y = D;
			}
			long[] z = eo ? Y : X;
			for(int q = 0;q < s;q++) {
				long a = X[q + 0];
				long b = X[q + s];
				z[q+0] = (a+b) % P;
				z[q+s] = (a-b+2*P) % P;
			}
		}

		//	private static void fft(long[] X, long[] Y)
		//	{
		//		int s = 1;
		//		boolean eo = false;
		//		for(int n = X.length;n >= 4;n /= 2) {
		//			int m = n/2;
		//			for(int p = 0;p < m;p++) {
		//				long wp = wps[s*p];
		//				for(int q = 0;q < s;q++) {
		//					long a = X[q + s*(p+0)];
		//					long b = X[q + s*(p+m)];
		//					Y[q + s*(2*p+0)] = (a+b) % P;
		//					Y[q + s*(2*p+1)] = (a-b+P) * wp % P;
		//				}
		//			}
		//			s *= 2;
		//			eo = !eo;
		//			long[] D = X; X = Y; Y = D;
		//		}
		//		long[] z = eo ? Y : X;
		//		for(int q = 0;q < s;q++) {
		//			long a = X[q + 0];
		//			long b = X[q + s];
		//			z[q+0] = (a+b) % P;
		//			z[q+s] = (a-b+P) % P;
		//		}
		//	}

		private static long[] go(long[] src, int n, boolean inverse)
		{
			long[] dst = Arrays.copyOf(src, n);
			fft(dst, new long[n]);
			if(inverse){
				long in = invl(n);
				for(int i = 0;i < n;i++){
					dst[i] = dst[i] * in % mod;
				}
			}

			return dst;
		}

		private static long pow(long a, long n) {
			//		a %= mod;
			long ret = 1;
			int x = 63 - Long.numberOfLeadingZeros(n);
			for (; x >= 0; x--) {
				ret = ret*ret % mod;
				if (n<<~x<0)ret = ret*a%mod;
			}
			return ret;
		}

		private static long invl(long a) {
			long b = mod;
			long p = 1, q = 0;
			while (b > 0) {
				long c = a / b;
				long d;
				d = a;
				a = b;
				b = d % b;
				d = p;
				p = q;
				q = d - c * q;
			}
			return p < 0 ? p + mod : p;
		}
	}

	public static long C(int n, int r, int mod, int[][] fif) {
		if (n < 0 || r < 0 || r > n) return 0;
		return (long) fif[0][n] * fif[1][r] % mod * fif[1][n - r] % mod;
	}

	public static int[][] enumFIF(int n, int mod) {
		int[] f = new int[n + 1];
		int[] invf = new int[n + 1];
		f[0] = 1;
		for (int i = 1; i <= n; i++) {
			f[i] = (int) ((long) f[i - 1] * i % mod);
		}
		long a = f[n];
		long b = mod;
		long p = 1, q = 0;
		while (b > 0) {
			long c = a / b;
			long d;
			d = a;
			a = b;
			b = d % b;
			d = p;
			p = q;
			q = d - c * q;
		}
		invf[n] = (int) (p < 0 ? p + mod : p);
		for (int i = n - 1; i >= 0; i--) {
			invf[i] = (int) ((long) invf[i + 1] * (i + 1) % mod);
		}
		return new int[][]{f, invf};
	}

	public static class DJSet {
		public int[] upper;

		public DJSet(int n) {
			upper = new int[n];
			Arrays.fill(upper, -1);
		}

		public int root(int x) {
			return upper[x] < 0 ? x : (upper[x] = root(upper[x]));
		}

		public boolean equiv(int x, int y) {
			return root(x) == root(y);
		}

		public boolean unite(int x, int y) {
			x = root(x);
			y = root(y);
			if (x != y) {
				if (upper[y] < upper[x]) {
					int d = x;
					x = y;
					y = d;
				}
				upper[x] += upper[y];
				upper[y] = x;
			}
			return x == y;
		}

		public int count() {
			int ct = 0;
			for (int u : upper) if (u < 0) ct++;
			return ct;
		}

		public int[][] toBucket() {
			int n = upper.length;
			int[][] ret = new int[n][];
			int[] rp = new int[n];
			for (int i = 0; i < n; i++) if (upper[i] < 0) ret[i] = new int[-upper[i]];
			for (int i = 0; i < n; i++) {
				int r = root(i);
				ret[r][rp[r]++] = i;
			}
			return ret;
		}
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new FastWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new F2().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private long[] nal(int n)
	{
		long[] a = new long[n];
		for(int i = 0;i < n;i++)a[i] = nl();
		return a;
	}

	private char[][] nm(int n, int m) {
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[][] nmi(int n, int m) {
		int[][] map = new int[n][];
		for(int i = 0;i < n;i++)map[i] = na(m);
		return map;
	}

	private int ni() { return (int)nl(); }

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	public static class FastWriter
	{
		private static final int BUF_SIZE = 1<<13;
		private final byte[] buf = new byte[BUF_SIZE];
		private final OutputStream out;
		private int ptr = 0;

		private FastWriter(){out = null;}

		public FastWriter(OutputStream os)
		{
			this.out = os;
		}

		public FastWriter(String path)
		{
			try {
				this.out = new FileOutputStream(path);
			} catch (FileNotFoundException e) {
				throw new RuntimeException("FastWriter");
			}
		}

		public FastWriter write(byte b)
		{
			buf[ptr++] = b;
			if(ptr == BUF_SIZE)innerflush();
			return this;
		}

		public FastWriter write(char c)
		{
			return write((byte)c);
		}

		public FastWriter write(char[] s)
		{
			for(char c : s){
				buf[ptr++] = (byte)c;
				if(ptr == BUF_SIZE)innerflush();
			}
			return this;
		}

		public FastWriter write(String s)
		{
			s.chars().forEach(c -> {
				buf[ptr++] = (byte)c;
				if(ptr == BUF_SIZE)innerflush();
			});
			return this;
		}

		private static int countDigits(int l) {
			if (l >= 1000000000) return 10;
			if (l >= 100000000) return 9;
			if (l >= 10000000) return 8;
			if (l >= 1000000) return 7;
			if (l >= 100000) return 6;
			if (l >= 10000) return 5;
			if (l >= 1000) return 4;
			if (l >= 100) return 3;
			if (l >= 10) return 2;
			return 1;
		}

		public FastWriter write(int x)
		{
			if(x == Integer.MIN_VALUE){
				return write((long)x);
			}
			if(ptr + 12 >= BUF_SIZE)innerflush();
			if(x < 0){
				write((byte)'-');
				x = -x;
			}
			int d = countDigits(x);
			for(int i = ptr + d - 1;i >= ptr;i--){
				buf[i] = (byte)('0'+x%10);
				x /= 10;
			}
			ptr += d;
			return this;
		}

		private static int countDigits(long l) {
			if (l >= 1000000000000000000L) return 19;
			if (l >= 100000000000000000L) return 18;
			if (l >= 10000000000000000L) return 17;
			if (l >= 1000000000000000L) return 16;
			if (l >= 100000000000000L) return 15;
			if (l >= 10000000000000L) return 14;
			if (l >= 1000000000000L) return 13;
			if (l >= 100000000000L) return 12;
			if (l >= 10000000000L) return 11;
			if (l >= 1000000000L) return 10;
			if (l >= 100000000L) return 9;
			if (l >= 10000000L) return 8;
			if (l >= 1000000L) return 7;
			if (l >= 100000L) return 6;
			if (l >= 10000L) return 5;
			if (l >= 1000L) return 4;
			if (l >= 100L) return 3;
			if (l >= 10L) return 2;
			return 1;
		}

		public FastWriter write(long x)
		{
			if(x == Long.MIN_VALUE){
				return write("" + x);
			}
			if(ptr + 21 >= BUF_SIZE)innerflush();
			if(x < 0){
				write((byte)'-');
				x = -x;
			}
			int d = countDigits(x);
			for(int i = ptr + d - 1;i >= ptr;i--){
				buf[i] = (byte)('0'+x%10);
				x /= 10;
			}
			ptr += d;
			return this;
		}

		public FastWriter write(double x, int precision)
		{
			if(x < 0){
				write('-');
				x = -x;
			}
			x += Math.pow(10, -precision)/2;
			//		if(x < 0){ x = 0; }
			write((long)x).write(".");
			x -= (long)x;
			for(int i = 0;i < precision;i++){
				x *= 10;
				write((char)('0'+(int)x));
				x -= (int)x;
			}
			return this;
		}

		public FastWriter writeln(char c){
			return write(c).writeln();
		}

		public FastWriter writeln(int x){
			return write(x).writeln();
		}

		public FastWriter writeln(long x){
			return write(x).writeln();
		}

		public FastWriter writeln(double x, int precision){
			return write(x, precision).writeln();
		}

		public FastWriter write(int... xs)
		{
			boolean first = true;
			for(int x : xs) {
				if (!first) write(' ');
				first = false;
				write(x);
			}
			return this;
		}

		public FastWriter write(long... xs)
		{
			boolean first = true;
			for(long x : xs) {
				if (!first) write(' ');
				first = false;
				write(x);
			}
			return this;
		}

		public FastWriter writeln()
		{
			return write((byte)'\n');
		}

		public FastWriter writeln(int... xs)
		{
			return write(xs).writeln();
		}

		public FastWriter writeln(long... xs)
		{
			return write(xs).writeln();
		}

		public FastWriter writeln(char[] line)
		{
			return write(line).writeln();
		}

		public FastWriter writeln(char[]... map)
		{
			for(char[] line : map)write(line).writeln();
			return this;
		}

		public FastWriter writeln(String s)
		{
			return write(s).writeln();
		}

		private void innerflush()
		{
			try {
				out.write(buf, 0, ptr);
				ptr = 0;
			} catch (IOException e) {
				throw new RuntimeException("innerflush");
			}
		}

		public void flush()
		{
			innerflush();
			try {
				out.flush();
			} catch (IOException e) {
				throw new RuntimeException("flush");
			}
		}

		public FastWriter print(byte b) { return write(b); }
		public FastWriter print(char c) { return write(c); }
		public FastWriter print(char[] s) { return write(s); }
		public FastWriter print(String s) { return write(s); }
		public FastWriter print(int x) { return write(x); }
		public FastWriter print(long x) { return write(x); }
		public FastWriter print(double x, int precision) { return write(x, precision); }
		public FastWriter println(char c){ return writeln(c); }
		public FastWriter println(int x){ return writeln(x); }
		public FastWriter println(long x){ return writeln(x); }
		public FastWriter println(double x, int precision){ return writeln(x, precision); }
		public FastWriter print(int... xs) { return write(xs); }
		public FastWriter print(long... xs) { return write(xs); }
		public FastWriter println(int... xs) { return writeln(xs); }
		public FastWriter println(long... xs) { return writeln(xs); }
		public FastWriter println(char[] line) { return writeln(line); }
		public FastWriter println(char[]... map) { return writeln(map); }
		public FastWriter println(String s) { return writeln(s); }
		public FastWriter println() { return writeln(); }
	}

	public void trnz(int... o)
	{
		for(int i = 0;i < o.length;i++)if(o[i] != 0)System.out.print(i+":"+o[i]+" ");
		System.out.println();
	}

	// print ids which are 1
	public void trt(long... o)
	{
		Queue<Integer> stands = new ArrayDeque<>();
		for(int i = 0;i < o.length;i++){
			for(long x = o[i];x != 0;x &= x-1)stands.add(i<<6|Long.numberOfTrailingZeros(x));
		}
		System.out.println(stands);
	}

	public void tf(boolean... r)
	{
		for(boolean x : r)System.out.print(x?'#':'.');
		System.out.println();
	}

	public void tf(boolean[]... b)
	{
		for(boolean[] r : b) {
			for(boolean x : r)System.out.print(x?'#':'.');
			System.out.println();
		}
		System.out.println();
	}

	public void tf(long[]... b)
	{
		if(INPUT.length() != 0) {
			for (long[] r : b) {
				for (long x : r) {
					for (int i = 0; i < 64; i++) {
						System.out.print(x << ~i < 0 ? '#' : '.');
					}
				}
				System.out.println();
			}
			System.out.println();
		}
	}

	public void tf(long... b)
	{
		if(INPUT.length() != 0) {
			for (long x : b) {
				for (int i = 0; i < 64; i++) {
					System.out.print(x << ~i < 0 ? '#' : '.');
				}
			}
			System.out.println();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}