Assume that sk(n) equals the sum of digits of number n in the k-based notation. For example, s2(5) = s2(1012) = 1 + 0 + 1 = 2, s3(14) = s3(1123) = 1 + 1 + 2 = 4.The sequence of integers a0, ..., an - 1 is defined as . Your task is to calculate the number of distinct subsequences of sequence a0, ..., an - 1. Calculate the answer modulo 109 + 7.Sequence a1, ..., ak is called to be a subsequence of sequence b1, ..., bl, if there is a sequence of indices 1 ≤ i1 < ... < ik ≤ l, such that a1 = bi1, ..., ak = bik. In particular, an empty sequence (i.e. the sequence consisting of zero elements) is a subsequence of any sequence.

The first line contains two space-separated numbers n and k (1 ≤ n ≤ 1018, 2 ≤ k ≤ 30).

In a single line print the answer to the problem modulo 109 + 7.

NoteIn the first sample the sequence ai looks as follows: (0, 1, 1, 0). All the possible subsequences are: (), (0), (0, 0), (0, 1), (0, 1, 0), (0, 1, 1), (0, 1, 1, 0), (1), (1, 0), (1, 1), (1, 1, 0).In the second sample the sequence ai looks as follows: (0, 1, 2, 3, 4, 5, 6). The subsequences of this sequence are exactly all increasing sequences formed from numbers from 0 to 6. It is easy to see that there are 27 = 128 such sequences.

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

public class EMain {
    String noResultMessage = "NoResult";
    Parser in = new Parser();
    PrintWriter out;

    long n = in.nextLong();
    int k = in.nextInteger();

    Matrix[] upRow(Matrix[] row){
        Matrix[] suffix = new Matrix[k];
        suffix[0] = Matrix.oneMatrix(k+1);
        for(int i = 1; i < k; ++i){
            suffix[i] = Matrix.mul(suffix[i-1], row[i-1]);
        }
        Matrix[] prefix = new Matrix[k];
        prefix[k-1] = row[k-1];
        for(int i = k-2; i>=0; --i){
            prefix[i] = Matrix.mul(row[i], prefix[i+1]);
        }
        Matrix[] result = new Matrix[k];
        for(int i = 0; i < k; ++i){
            result[i] = Matrix.mul(prefix[i], suffix[i]);
        }
        return result;
    }

    public void solve() {

        Matrix[][] matrixes = new Matrix[100][k];

        for(int i = 0; i < k; ++i){
            Matrix m = Matrix.oneMatrix(k + 1);
            matrixes[0][i] = m;
            for(int j = 0; j <= k; ++j){
                m.set(j, i, 1);
            }
        }
        int[] digits = new int[100];
        int index = 0;
        long limit = n;
        digits[index++] = (int) (limit % k);
        for(int row = 1; row < 100; ++row){
            limit /= k;
            if(limit == 0)break;
            digits[index++] = (int) (limit % k);
            matrixes[row] = upRow(matrixes[row-1]);
        }

        Matrix result = Matrix.oneMatrix(k+1);
        int pos = 0;
        while(index-- > 0){
            while(digits[index]-- > 0){
                result = Matrix.mul(result, matrixes[index][pos++]);
                pos %= k;
            }
        }
        Vector vec = new Vector(k+1);
        vec.set(k, 1);
        out.println(Vector.mul(vec, result).sum());

    }

    static int MOD = (int) (1e9+7);

    static public class Matrix {
        int[][] data;

        public Matrix(int size) {
            this.data = new int[size][size];
        }

        Matrix(Matrix other) {
            int size = other.data.length;
            this.data = new int[size][];
            for(int i = 0; i < size; ++i){
                this.data[i] = Arrays.copyOf(other.data[i], size);
            }
        }
        public void set(int row, int column, int value){
            data[row][column] = value;
        }

        public static Matrix oneMatrix(int size){
            Matrix result = new Matrix(size);
            for(int i = 0; i < size; ++i){
                result.data[i][i] = 1;
            }
            return result;
        }

        public static Matrix mul(Matrix left, Matrix right){
            int size = left.data.length;
            assert size == right.data.length;
            Matrix result = new Matrix(size);
            for(int i = 0; i < size; ++i){
                for(int j = 0; j < size; ++j){
                    int val = 0;
                    for(int k = 0; k < size; ++k){
                        val += 1l * left.data[i][k] * right.data[k][j] % MOD;
                        val %= MOD;
                        val += MOD;
                        val %= MOD;
                    }
                    result.data[i][j] = val;
                }
            }
            return result;
        }

        static Matrix degree(Matrix matrix, long degree){
            Matrix result = Matrix.oneMatrix(matrix.data.length);
            while(degree > 0){
                if((degree & 1) == 1){
                    result = Matrix.mul(result, matrix);
                }
                result = Matrix.mul(result, result);
                degree >>= 1;
            }
            return result;
        }
    }

    static public class Vector{
        int[] data;

        public Vector(int size) {
            this.data = new int[size];
        }

        Vector(Vector other) {
            this.data = Arrays.copyOf(other.data, other.data.length);
        }

        public void set(int pos, int val){
            data[pos] = val;
        }

        int get(int pos){
            return data[pos];
        }

        public int sum(){
            long sum = 0;
            for(int i : data){
                sum += i;
            }
            sum %= MOD;
            sum += MOD;
            sum %= MOD;
            return (int) sum;
        }

        public static Vector mul(Vector vec, Matrix matrix){
            int size = vec.data.length;
            assert size == matrix.data.length;
            Vector result = new Vector(size);
            for(int i = 0; i < size; ++i){
                int val = 0;
                for(int j = 0; j < size; ++j){
                    val += 1l * vec.data[j] * matrix.data[j][i] % MOD;
                    val += MOD;
                    val %= MOD;
                }
                result.data[i] = val;
            }
            return result;
        }
    }

    static public class Parser{
        Scanner scanner;

        public Parser() {
            scanner = new Scanner(System.in).useLocale(Locale.ENGLISH);
        }

        public Parser(String str) {
            scanner = new Scanner(str).useLocale(Locale.ENGLISH);
        }

        long nextLong(){
            return scanner.nextLong();
        }

        int nextInteger(){
            return scanner.nextInt();
        }

        double nextDouble(){
            return scanner.nextDouble();
        }

        String nextLine(){
            return scanner.nextLine();
        }

        String next(){
            return scanner.next();
        }

        int[] nextIntegers(int count){
            int[] result = new int[count];
            for(int i = 0; i < count; ++i){
                result[i] = nextInteger();
            }
            return result;
        }

        long[] nextLongs(int count){
            long[] result = new long[count];
            for(int i = 0; i < count; ++i){
                result[i] = nextLong();
            }
            return result;
        }

        int[][] nextIntegers(int fields, int count){
            int[][] result = new int[fields][count];
            for(int c = 0; c < count; ++c){
                for(int i = 0; i < fields; ++i){
                    result[i][c] = nextInteger();
                }
            }
            return result;
        }
    }

    void noResult(){
        throw new NoResultException();
    }

    void noResult(String str){
        throw new NoResultException(str);
    }

    void run(){
        try{
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            out = new PrintWriter(outStream);
            solve();
            out.close();
            System.out.print(outStream.toString());
        } catch (NoResultException exc){
            System.out.print(null == exc.response ? noResultMessage : exc.response);
        }
    }

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

    public static class NoResultException extends RuntimeException{
        private String response;

        public NoResultException(String response) {
            this.response = response;
        }

        public NoResultException() {
        }
    }
}

//package round283;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class E {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	// 012 120 201
	// 1 1 2 4 6 10 23 33 56
	void solve()
	{
		long n = nl();
		int K = ni();

		if(n <= K){
			int u = 1;
			for(int i = 0;i < n;i++){
				u = u * 2 % mod;
			}
			out.println(u);
			return;
		}

		int t = (int)(Math.log(10)*18/Math.log(K) + 1);
		int[][][] B = new int[2*K][2*K+1][2*K+1];

		int mod = 1000000007;
		for(int i = 0;i < 2*K;i++){
			for(int j = 1;j < 2*K+1;j++){
				B[i][j][j-1] = 1;
			}
			B[i][0][0] = 2;
			B[i][0][i] += mod-1;
		}
		int[][][] C = new int[K][][];
		for(int i = 0;i < K;i++){
			if(i == 0){
				C[i] = pow(B[K-i], K-i);
			}else{
				C[i] = mul(pow(B[2*K-i], i), pow(B[K-i], K-i));
			}
		}

		int[][][] M = new int[t+1][][];
		int[][][] MK = new int[t+1][][];
		int[][][] MKT = new int[t+1][][];
		M[1] = C[1];
		MK[1] = pow(C[1], K-1);
		MKT[1] = MK[1];
		for(int z = 2;z < t;z++){
			M[z] = mul(MKT[z-1], C[z%K]);
//			M[z] = C[z%K];
//			for(int y = 1;y < z;y++){
//				M[z] = mul(MK[y], M[z]);
//			}
			MK[z] = pow(M[z], K-1);
			MKT[z] = mul(MK[z], MKT[z-1]);
		}
		int[][][] rem = new int[t+1][][];
		rem[1] = MK[1];
		for(int z = 2;z < t;z++){
			rem[z] = mul(MK[z], rem[z-1]);
		}

		long[] d = new long[64];
		int p = 0;
		while(n > 0){
			d[p++] = n % K;
			n /= K;
		}

		int[] v = new int[2*K+1];
		v[K] = 1;
		for(int i = K-1;i >= 0;i--){
			v[i] = v[i+1] * 2 % mod;
		}

		int prev = -1;
		for(int u = p-1;u >= 2;u--){
			long e = d[u];
			for(int i = 0;i < e;i++){
				if(prev != -1)v = mul(C[prev], v);
				v = mul(rem[u-1], v);
				prev = u%K;
			}
		}
		{
			int u = 1;
			long e = d[u];
			if(e > 0){
				if(prev != -1)v = mul(C[prev], v);
				for(int i = 1;i < e;i++){
					v = mul(C[1], v);
					prev = u%K;
				}
				prev = 1;
			}
		}
		if(prev == -1)prev = 1;
		for(int j = 0;j < K-prev && d[0] > 0;j++, d[0]--){
			v = mul(B[K-prev], v);
		}
		for(int j = 0;j < prev && d[0] > 0;j++, d[0]--){
			v = mul(B[2*K-prev], v);
		}
		out.println(v[0]);
	}

	public static int[][] mul(int[][] A, int[][] B)
	{
		int m = A.length;
		int n = A[0].length;
		int o = B[0].length;
		int[][] C = new int[m][o];
		for(int i = 0;i < m;i++){
			long[] sum = new long[n];
			for(int k = 0;k < n;k++){
				for(int j = 0;j < n;j++){
					sum[j] += (long)A[i][k] * B[k][j];
					if(sum[j] >= BIG)sum[j] -= BIG;
				}
			}
			for(int j = 0;j < n;j++){
				C[i][j] = (int)(sum[j] % mod);
			}
		}
		return C;
	}

	///////// begin
	public static final int mod = 1000000007;
	public static final long m2 = (long)mod*mod;
	public static final long BIG = 8L*m2;

	// A^e*v
	public static int[] pow(int[][] A, int[] v, long e)
	{
		for(int i = 0;i < v.length;i++){
			if(v[i] >= mod)v[i] %= mod;
		}
		int[][] MUL = A;
		for(;e > 0;e>>>=1) {
			if((e&1)==1)v = mul(MUL, v);
			MUL = p2(MUL);
		}
		return v;
	}

	// int matrix*int vector
	public static int[] mul(int[][] A, int[] v)
	{
		int m = A.length;
		int n = v.length;
		int[] w = new int[m];
		for(int i = 0;i < m;i++){
			long sum = 0;
			for(int k = 0;k < n;k++){
				sum += (long)A[i][k] * v[k];
				if(sum >= BIG)sum -= BIG;
			}
			w[i] = (int)(sum % mod);
		}
		return w;
	}

	// int matrix^2 (be careful about minus value)
	public static int[][] p2(int[][] A)
	{
		int n = A.length;
		int[][] C = new int[n][n];
		for(int i = 0;i < n;i++){
			long[] sum = new long[n];
			for(int k = 0;k < n;k++){
				for(int j = 0;j < n;j++){
					sum[j] += (long)A[i][k] * A[k][j];
					if(sum[j] >= BIG)sum[j] -= BIG;
				}
			}
			for(int j = 0;j < n;j++){
				C[i][j] = (int)(sum[j] % mod);
			}
		}
		return C;
	}

	//////////// end

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

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

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

	private byte[] inbuf = new byte[1024];
	private 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;

	}

	public static int[][] pow(int[][] A, long e)
	{
		int[][] MUL = A;
		int n = A.length;
		int[][] C = new int[n][n];
		for(int i = 0;i < n;i++)C[i][i] = 1;
		for(;e > 0;e>>>=1) {
			if((e&1)==1)C = mul(C, MUL);
			MUL = p2(MUL);
		}
		return C;
	}

	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(!oj)System.out.println(Arrays.deepToString(o)); }
}

//package round283;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class E {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	// 012 120 201
	// 1 1 2 4 6 10 23 33 56
	void solve()
	{
		long n = nl();
		int K = ni();

		if(n <= K){
			int u = 1;
			for(int i = 0;i < n;i++){
				u = u * 2 % mod;
			}
			out.println(u);
			return;
		}

		int t = (int)(Math.log(10)*18/Math.log(K) + 1);
		int[][][] B = new int[2*K][2*K][2*K];

		int mod = 1000000007;
		for(int i = 0;i < 2*K;i++){
			for(int j = 1;j < 2*K;j++){
				B[i][j][j-1] = 1;
			}
			B[i][0][0] = 2;
			B[i][0][i] += mod-1;
		}
		int[][][] C = new int[K][][];
		for(int i = 0;i < K;i++){
			if(i == 0){
				C[i] = pow(B[K-i], K-i);
			}else{
				C[i] = mul(pow(B[2*K-i], i), pow(B[K-i], K-i));
			}
		}

		int[][][] M = new int[t+1][][];
		int[][][] MK = new int[t+1][][];
		int[][][] MKT = new int[t+1][][];
		M[1] = C[1];
		MK[1] = pow(C[1], K-1);
		MKT[1] = MK[1];
		for(int z = 2;z < t;z++){
			M[z] = mul(MKT[z-1], C[z%K]);
//			M[z] = C[z%K];
//			for(int y = 1;y < z;y++){
//				M[z] = mul(MK[y], M[z]);
//			}
			MK[z] = pow(M[z], K-1);
			MKT[z] = mul(MK[z], MKT[z-1]);
		}
		int[][][] rem = new int[t+1][][];
		rem[1] = MK[1];
		for(int z = 2;z < t;z++){
			rem[z] = mul(MK[z], rem[z-1]);
		}

		long[] d = new long[64];
		int p = 0;
		while(n > 0){
			d[p++] = n % K;
			n /= K;
		}

		int[] v = new int[2*K];
		v[K] = 1;
		for(int i = K-1;i >= 0;i--){
			v[i] = v[i+1] * 2 % mod;
		}

		int prev = -1;
		for(int u = p-1;u >= 2;u--){
			long e = d[u];
			for(int i = 0;i < e;i++){
				if(prev != -1)v = mul(C[prev], v);
				v = mul(rem[u-1], v);
				prev = u%K;
			}
		}
		{
			int u = 1;
			long e = d[u];
			if(e > 0){
				if(prev != -1)v = mul(C[prev], v);
				for(int i = 1;i < e;i++){
					v = mul(C[1], v);
					prev = u%K;
				}
				prev = 1;
			}
		}
		if(prev == -1)prev = 1;
		for(int j = 0;j < K-prev && d[0] > 0;j++, d[0]--){
			v = mul(B[K-prev], v);
		}
		for(int j = 0;j < prev && d[0] > 0;j++, d[0]--){
			v = mul(B[2*K-prev], v);
		}
		out.println(v[0]);
	}

	public static int[][] mul(int[][] A, int[][] B)
	{
		int m = A.length;
		int n = A[0].length;
		int o = B[0].length;
		int[][] C = new int[m][o];
		for(int i = 0;i < m;i++){
			long[] sum = new long[n];
			for(int k = 0;k < n;k++){
				for(int j = 0;j < n;j++){
					sum[j] += (long)A[i][k] * B[k][j];
					if(sum[j] >= BIG)sum[j] -= BIG;
				}
			}
			for(int j = 0;j < n;j++){
				C[i][j] = (int)(sum[j] % mod);
			}
		}
		return C;
	}

	///////// begin
	public static final int mod = 1000000007;
	public static final long m2 = (long)mod*mod;
	public static final long BIG = 8L*m2;

	// A^e*v
	public static int[] pow(int[][] A, int[] v, long e)
	{
		for(int i = 0;i < v.length;i++){
			if(v[i] >= mod)v[i] %= mod;
		}
		int[][] MUL = A;
		for(;e > 0;e>>>=1) {
			if((e&1)==1)v = mul(MUL, v);
			MUL = p2(MUL);
		}
		return v;
	}

	// int matrix*int vector
	public static int[] mul(int[][] A, int[] v)
	{
		int m = A.length;
		int n = v.length;
		int[] w = new int[m];
		for(int i = 0;i < m;i++){
			long sum = 0;
			for(int k = 0;k < n;k++){
				sum += (long)A[i][k] * v[k];
				if(sum >= BIG)sum -= BIG;
			}
			w[i] = (int)(sum % mod);
		}
		return w;
	}

	// int matrix^2 (be careful about minus value)
	public static int[][] p2(int[][] A)
	{
		int n = A.length;
		int[][] C = new int[n][n];
		for(int i = 0;i < n;i++){
			long[] sum = new long[n];
			for(int k = 0;k < n;k++){
				for(int j = 0;j < n;j++){
					sum[j] += (long)A[i][k] * A[k][j];
					if(sum[j] >= BIG)sum[j] -= BIG;
				}
			}
			for(int j = 0;j < n;j++){
				C[i][j] = (int)(sum[j] % mod);
			}
		}
		return C;
	}

	//////////// end

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

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

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

	private byte[] inbuf = new byte[1024];
	private 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;

	}

	public static int[][] pow(int[][] A, long e)
	{
		int[][] MUL = A;
		int n = A.length;
		int[][] C = new int[n][n];
		for(int i = 0;i < n;i++)C[i][i] = 1;
		for(;e > 0;e>>>=1) {
			if((e&1)==1)C = mul(C, MUL);
			MUL = p2(MUL);
		}
		return C;
	}

	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(!oj)System.out.println(Arrays.deepToString(o)); }
}

import java.util.*;
import static java.lang.Math.*;

public class E {
    static void p(Object ...args) {System.out.println(Arrays.deepToString(args));}
    static long MOD = 1_000_000_007;

    /*static int score(int a, int k) {
        int ans = 0;
        while( a > 0) {
            ans += a % k;
            a /= k;
        }
        return ans % k;
    }

    public static long slow(int N, int K) {
        long[] V = new long[N+1];
        for (int i = 0; i <= N; i++)
            V[i] = score(i, K);
        long[] dp = new long[N+1];
        for (int i = 0; i <= N; i++) {
            for (int j = 0; j < K; j++) {
                for (int a = i - 1; a >= 0; a--) {
                    if (V[a] == j) {
                        dp[i] += dp[a];
                        break;
                    }
                }
            }
            dp[i] += 1;
            dp[i] %= MOD;
        }
        return dp[N];
    }*/
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        long N = in.nextLong();
        int K = in.nextInt();

        int need = 4;
        long temp2 = N + 100000;
        while (temp2 > 0) {
            need++;
            temp2 /= K;
        }

        long[][][] M = new long[need][][];
        for (int i = 2; i < M.length; i++)
            M[i] = makeMatrix(K, i);

        /*p("M[2]");
        for (int i = 0; i < M[2].length; i++)
            p(M[2][i]);
        p("M[3]");
        for (int i = 0; i < M[3].length; i++)
            p(M[3][i]);*/

        long[][][] moveBy = new long[need][][];
        long[][][] moveByK = new long[need][][];
        for (int i = 1; i < moveBy.length - 1; i++) {
            long[][] ans = new long[K+1][K+1];
            for (int j = 0; j < ans.length; j++)
                ans[j][j] = 1;
            for (int j = i - 1; j >= 1; j--)
                ans = multiply(ans, moveByK[j]);

            ans = multiply(ans, M[i+1]);
            moveBy[i] = ans;
            moveByK[i] = new long[K+1][K+1];
            for (int j = 0; j <= K; j++)
                moveByK[i][j][j] = 1;
            moveByK[i] = pow(moveBy[i], K-1);
            /*for (int j = 0; j < K-1; j++)
                moveByK[i] = multiply(moveByK[i], moveBy[i]);*/
        }
        /*p("moveBy[2]");
        for (int i = 0; i <= K; i++)
            p(moveBy[2][i]);*/

        long at = 0;
        long[][] f = new long[K+1][K+1];
        for (int i = 0; i < f.length; i++)
            f[i][i] = 1;
        //f = multiply(f, M[2]);
        //f = multiply(f, M[3]);
        long temp = N / K;
        for (int i = 1; temp > 0; i++) {
            f = multiply(pow(moveBy[i], (int)(temp % K)), f);
            temp /= K;
        }
        /*p("f");
        for (int i = 0; i < K+1; i++)
            p(f[i]);*/
        long[] start = new long[K+1];
        for (int i = 0; i < start.length; i++)
            start[i] = (1L<<(i)) % MOD;
        start[K] = 1;

        int position = (int)(N % K);
        //p("taking: ", position);
        long ans = 0;
        for (int i = 0; i < start.length; i++)
            ans += (start[i] * f[i][position]) % MOD;
        ans %= MOD;

        /*long a2 = slow((int)N, K);
        if (ans != a2) {
            p(ans, a2);
            throw new RuntimeException();
        }*/
        System.out.println(ans);
    }
    static long[][] pow(long[][] M, int p) {
        long[][] ans = new long[M.length][M.length];
        for (int i = 0; i < ans.length ;i++)
            ans[i][i] = 1;
        long[][] go = new long[M.length][M.length];
        for (int i = 0; i < go.length ;i++)
            for (int j = 0; j < go.length ;j++)
                go[i][j] = M[i][j];
        while (p > 0) {
            if (p % 2 == 1) {
                ans = multiply(ans, go);
            }
            p /= 2;
            go = multiply(go, go);
        }
        return ans;
    }
    static long[][] makeMatrix(int K, int a) {
        long[][] res = new long[K+1][K+1];

        int[] v = new int[2*K];
        v[2*K-1] = 0;
        for (int i = 2*K-2; i >= 0; i--) {
            if (i == K-1) {
                v[i] = (K + (K-a + v[i+1]) % K) % K;
            } else {
                v[i] = (K + (K-1 + v[i+1]) % K) % K;
            }
        }
        /*if (a == 2 || a == 3) {
            p(a, v);
        }*/
        for (int i = 0; i <= K; i++)
            res[K][i]++;
        for (int c = 0; c < K; c++) {
            for (int i = 0; i < K; i++) {
                boolean found = false;
                for (int j = c - 1 + K; j >= 0; j--) {
                    if (v[j] == i) {
                        found = true;
                        if (j < K) {
                            res[j][c] += 1;
                        } else {
                            for (int b = 0; b <= K; b++)
                                res[b][c] += res[b][j-K];
                        }
                        break;
                    }
                }
                if (!found) {
                    p(c, i, v);
                    throw new RuntimeException();
                }
            }
        }
        return res;
    }
    static long[][] multiply(long[][] A, long[][] B) {
        long[][] res = new long[A.length][A.length];
        for (int r = 0; r < A.length; r++)
            for (int c = 0; c < A.length; c++) {
                for (int i = 0; i < A.length; i++)
                    res[r][c] += (A[r][i] * B[i][c]) % MOD;
                res[r][c] %= MOD;
            }
        return res;
    }
 }

import java.util.*;
import static java.lang.Math.*;

public class E {
    static void p(Object ...args) {System.out.println(Arrays.deepToString(args));}
    static long MOD = 1_000_000_007;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        long N = in.nextLong();
        int K = in.nextInt();

        int need = 4;
        long temp2 = N + 100000;
        while (temp2 > 0) {
            need++;
            temp2 /= K;
        }

        long[][][] moveBy = new long[need][][];
        long[][] prefix = identity(K+1);
        for (int i = 1; i < need - 1; i++) {
            moveBy[i] = multiply(prefix, makeMatrix(K, i+1));
            prefix = multiply(pow(moveBy[i], K-1), prefix);
        }

        long at = 0;
        long[][] f = identity(K+1);
        long temp = N / K;
        for (int i = 1; temp > 0; i++) {
            f = multiply(pow(moveBy[i], (int)(temp % K)), f);
            temp /= K;
        }
        long[] start = new long[K+1];
        for (int i = 0; i < start.length; i++)
            start[i] = (1L<<(i)) % MOD;
        start[K] = 1;

        int position = (int)(N % K);
        long ans = 0;
        for (int i = 0; i < start.length; i++)
            ans += (start[i] * f[i][position]) % MOD;
        ans %= MOD;

        System.out.println(ans);
    }
    static long[][] identity(int A) {
        long[][] ans = new long[A][A];
        for (int i = 0; i < A; i++)
            ans[i][i] = 1;
        return ans;
    }
    static long[][] pow(long[][] M, int p) {
        long[][] ans = new long[M.length][M.length];
        for (int i = 0; i < ans.length ;i++)
            ans[i][i] = 1;
        long[][] go = new long[M.length][M.length];
        for (int i = 0; i < go.length ;i++)
            for (int j = 0; j < go.length ;j++)
                go[i][j] = M[i][j];
        while (p > 0) {
            if (p % 2 == 1) {
                ans = multiply(ans, go);
            }
            p /= 2;
            go = multiply(go, go);
        }
        return ans;
    }
    static long[][] makeMatrix(int K, int a) {
        long[][] res = new long[K+1][K+1];

        int[] v = new int[2*K];
        v[2*K-1] = 0;
        for (int i = 2*K-2; i >= 0; i--) {
            if (i == K-1) {
                v[i] = (K + (K-a + v[i+1]) % K) % K;
            } else {
                v[i] = (K + (K-1 + v[i+1]) % K) % K;
            }
        }
        for (int i = 0; i <= K; i++)
            res[K][i]++;
        for (int c = 0; c < K; c++) {
            for (int i = 0; i < K; i++) {
                boolean found = false;
                for (int j = c - 1 + K; j >= 0; j--) {
                    if (v[j] == i) {
                        found = true;
                        if (j < K) {
                            res[j][c] += 1;
                        } else {
                            for (int b = 0; b <= K; b++)
                                res[b][c] += res[b][j-K];
                        }
                        break;
                    }
                }
                if (!found) {
                    p(c, i, v);
                    throw new RuntimeException();
                }
            }
        }
        return res;
    }
    static long[][] multiply(long[][] A, long[][] B) {
        long[][] res = new long[A.length][A.length];
        for (int r = 0; r < A.length; r++)
            for (int c = 0; c < A.length; c++) {
                for (int i = 0; i < A.length; i++)
                    res[r][c] += (A[r][i] * B[i][c]) % MOD;
                res[r][c] %= MOD;
            }
        return res;
    }
 }

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.math.BigInteger;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.StringTokenizer;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
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);
		TaskE solver = new TaskE();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE {
    private static final long MODULO = (long) 1e9 + 7;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        long n = in.nextLong();
        int k = in.nextInt();
        long[][][] a = new long[k][k + 1][k + 1];
        for (int i = 0; i < k; ++i) {
            long[][] mat = a[i];
            for (int j = 0; j < k; ++j) if (j != i) mat[j][j] = 1;
            mat[i][k] = 1;
            mat[k][k] = 2;
            mat[k][i] = MODULO - 1;
        }
        int sum = 0;
        for (long m = n; m > 0; m /= k) sum += m % k;
        long[][] mul = new long[k + 1][k + 1];
        for (int i = 0; i < mul.length; ++i) mul[i][i] = 1;
        while (n > 0) {
            sum -= n % k;
            for (int i = (int) (n % k - 1); i >= 0; --i) mul = multiply(mul, a[(sum + i) % k]);
            long[][][] prefix = new long[k][][];
            for (int i = 0; i < k; ++i) {
                if (i == 0) prefix[i] = a[i];
                else prefix[i] = multiply(a[i], prefix[i - 1]);
            }
            long[][][] suffix = new long[k][][];
            for (int i = k - 1; i >= 0; --i) {
                if (i == k - 1) suffix[i] = a[i];
                else suffix[i] = multiply(suffix[i + 1], a[i]);
            }
            for (int i = 0; i < k; ++i) {
                if (i == 0) a[i] = suffix[i];
                else a[i] = multiply(prefix[i - 1], suffix[i]);
            }
            n /= k;
        }
        long[][] res = new long[k + 1][1];
        res[k][0] = 1;
        res = multiply(mul, res);
        out.println(res[k][0]);
    }

    long[][] multiply(long[][] a, long[][] b) {
        int m = a.length;
        int n = a[0].length;
        int p = b[0].length;
        long[][] c = new long[m][p];
        for (int i = 0; i < m; ++i)
            for (int j = 0; j < n; ++j)
                for (int k = 0; k < p; ++k)
                    c[i][k] = (c[i][k] + a[i][j] * b[j][k]) % MODULO;
        return c;
    }
}

class InputReader {
    private final BufferedReader bufferedReader;
    private StringTokenizer stringTokenizer;

    public InputReader(InputStream inputStream) {
        this.bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        this.stringTokenizer = null;
    }

    public String next() {
        while (stringTokenizer == null || !stringTokenizer.hasMoreTokens()) {
            try {
                stringTokenizer = new StringTokenizer(bufferedReader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return stringTokenizer.nextToken();
    }

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

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

}

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.StringTokenizer;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
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);
		TaskE solver = new TaskE();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE {
    static final long MODULO = (long) (1e9 + 7);
    static final long BIG = Long.MAX_VALUE - Long.MAX_VALUE % MODULO;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        long n = in.nextLong();
        int k = in.nextInt();
        long pk = 1;
        int pow = 0;
        while (pk <= n / k) {
            pk *= k;
            ++pow;
        }
        matrCache = new long[pow + 1][][];
        long at = 0;
        long[] ways = new long[k + 1];
        ways[k] = 1;
        while (at < n) {
            while (at + pk <= n) {
                long[][] matr = getMatr(digitSum(at, k) % k, k, pow);
                ways = mul(matr, ways);
                at += pk;
            }
            pk /= k;
            --pow;
        }
        long res = 0;
        for (long x : ways) res += x;
        res %= MODULO;
        out.println(res);
    }

    long[][][] matrCache;

    private long[][] getMatr(int pre, int k, int pow) {
        long[][] res = matrCache[pow];
        if (res == null) {
            if (pow == 0) {
                res = new long[k + 1][k + 1];
                for (int i = 0; i < k + 1; ++i) ++res[i][i];
                for (int i = 0; i < k + 1; ++i) {
                    ++res[0][i];
                }
                --res[0][0];
            } else {
                res = new long[k + 1][k + 1];
                for (int i = 0; i < k + 1; ++i) ++res[i][i];
                for (int i = 0; i < k; ++i) {
                    res = mul(getMatr(i, k, pow - 1), res);
                }
            }
            matrCache[pow] = res;
        }
        long[][] rotated = new long[k + 1][k + 1];
        for (int i = 0; i <= k; ++i)
            for (int j = 0; j <= k; ++j) {
                int ii = (i == k) ? k : (pre + i) % k;
                int jj = (j == k) ? k : (pre + j) % k;
                rotated[ii][jj] = res[i][j];
            }
        return rotated;
    }

    private long[] mul(long[][] a, long[] b) {
        long[] c = new long[b.length];
        for (int i = 0; i < c.length; ++i) {
            long s = 0;
            for (int j = 0; j < c.length; ++j) {
                s += a[i][j] * b[j];
                if (s < 0) s -= BIG;
            }
            c[i] = s % MODULO;
        }
        return c;
    }

    private long[][] mul(long[][] a, long[][] b) {
        long[][] c = new long[b.length][b.length];
        for (int i = 0; i < c.length; ++i) {
            for (int k = 0; k < c.length; ++k) {
                long s = 0;
                for (int j = 0; j < c.length; ++j) {
                    s += a[i][j] * b[j][k];
                    if (s < 0) s -= BIG;
                }
                c[i][k] = s % MODULO;
            }
        }
        return c;
    }

    private int digitSum(long at, int k) {
        int res = 0;
        while (at > 0) {
            res += at % k;
            at /= k;
        }
        return res;
    }
}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream), 32768);
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

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

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

}

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

public class EMain {
    String noResultMessage = "NoResult";
    Parser in = new Parser();
    PrintWriter out;

    long n = in.nextLong();
    int k = in.nextInteger();

    Matrix[] upRow(Matrix[] row){
        Matrix[] result = new Matrix[k];
        for(int i = 0; i < k; ++i){
            Matrix m = Matrix.oneMatrix(k+1);
            for(int j = 0; j < k; ++j){
                m = Matrix.mul(m, row[(i+j)%k]);
            }
            result[i] = m;
        }
        return result;
    }

    public void solve() {

        Matrix[][] matrixes = new Matrix[100][k];

        for(int i = 0; i < k; ++i){
            Matrix m = Matrix.oneMatrix(k + 1);
            matrixes[0][i] = m;
            for(int j = 0; j <= k; ++j){
                m.set(j, i, 1);
            }
        }
        int[] digits = new int[100];
        int index = 0;
        long limit = n;
        digits[index++] = (int) (limit % k);
        for(int row = 1; row < 100; ++row){
            limit /= k;
            if(limit == 0)break;
            digits[index++] = (int) (limit % k);
            matrixes[row] = upRow(matrixes[row-1]);
        }

        Matrix result = Matrix.oneMatrix(k+1);
        int pos = 0;
        while(index-- > 0){
            while(digits[index]-- > 0){
                result = Matrix.mul(result, matrixes[index][pos++]);
            }
        }
        Vector vec = new Vector(k+1);
        vec.set(k, 1);
        out.println(Vector.mul(vec, result).sum());

    }

    static int MOD = (int) (1e9+7);

    static public class Matrix {
        int[][] data;

        public Matrix(int size) {
            this.data = new int[size][size];
        }

        Matrix(Matrix other) {
            int size = other.data.length;
            this.data = new int[size][];
            for(int i = 0; i < size; ++i){
                this.data[i] = Arrays.copyOf(other.data[i], size);
            }
        }
        public void set(int row, int column, int value){
            data[row][column] = value;
        }

        public static Matrix oneMatrix(int size){
            Matrix result = new Matrix(size);
            for(int i = 0; i < size; ++i){
                result.data[i][i] = 1;
            }
            return result;
        }

        public static Matrix mul(Matrix left, Matrix right){
            int size = left.data.length;
            assert size == right.data.length;
            Matrix result = new Matrix(size);
            for(int i = 0; i < size; ++i){
                for(int j = 0; j < size; ++j){
                    int val = 0;
                    for(int k = 0; k < size; ++k){
                        val += 1l * left.data[i][k] * right.data[k][j] % MOD;
                        val += MOD;
                        val %= MOD;
                    }
                    result.data[i][j] = val;
                }
            }
            return result;
        }

        static Matrix degree(Matrix matrix, long degree){
            Matrix result = Matrix.oneMatrix(matrix.data.length);
            while(degree > 0){
                if((degree & 1) == 1){
                    result = Matrix.mul(result, matrix);
                }
                result = Matrix.mul(result, result);
                degree >>= 1;
            }
            return result;
        }
    }

    static public class Vector{
        int[] data;

        public Vector(int size) {
            this.data = new int[size];
        }

        Vector(Vector other) {
            this.data = Arrays.copyOf(other.data, other.data.length);
        }

        public void set(int pos, int val){
            data[pos] = val;
        }

        int get(int pos){
            return data[pos];
        }

        public int sum(){
            long sum = 0;
            for(int i : data){
                sum += i;
            }
            sum %= MOD;
            sum += MOD;
            sum %= MOD;
            return (int) sum;
        }

        public static Vector mul(Vector vec, Matrix matrix){
            int size = vec.data.length;
            assert size == matrix.data.length;
            Vector result = new Vector(size);
            for(int i = 0; i < size; ++i){
                int val = 0;
                for(int j = 0; j < size; ++j){
                    val += 1l * vec.data[j] * matrix.data[j][i] % MOD;
                    val += MOD;
                    val %= MOD;
                }
                result.data[i] = val;
            }
            return result;
        }
    }

    static public class Parser{
        Scanner scanner;

        public Parser() {
            scanner = new Scanner(System.in).useLocale(Locale.ENGLISH);
        }

        public Parser(String str) {
            scanner = new Scanner(str).useLocale(Locale.ENGLISH);
        }

        long nextLong(){
            return scanner.nextLong();
        }

        int nextInteger(){
            return scanner.nextInt();
        }

        double nextDouble(){
            return scanner.nextDouble();
        }

        String nextLine(){
            return scanner.nextLine();
        }

        String next(){
            return scanner.next();
        }

        int[] nextIntegers(int count){
            int[] result = new int[count];
            for(int i = 0; i < count; ++i){
                result[i] = nextInteger();
            }
            return result;
        }

        long[] nextLongs(int count){
            long[] result = new long[count];
            for(int i = 0; i < count; ++i){
                result[i] = nextLong();
            }
            return result;
        }

        int[][] nextIntegers(int fields, int count){
            int[][] result = new int[fields][count];
            for(int c = 0; c < count; ++c){
                for(int i = 0; i < fields; ++i){
                    result[i][c] = nextInteger();
                }
            }
            return result;
        }
    }

    void noResult(){
        throw new NoResultException();
    }

    void noResult(String str){
        throw new NoResultException(str);
    }

    void run(){
        try{
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            out = new PrintWriter(outStream);
            solve();
            out.close();
            System.out.print(outStream.toString());
        } catch (NoResultException exc){
            System.out.print(null == exc.response ? noResultMessage : exc.response);
        }
    }

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

    public static class NoResultException extends RuntimeException{
        private String response;

        public NoResultException(String response) {
            this.response = response;
        }

        public NoResultException() {
        }
    }
}

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

public class EMain {
    String noResultMessage = "NoResult";
    Parser in = new Parser();
    PrintWriter out;

    long n = in.nextLong();
    int k = in.nextInteger();

    Matrix[] upRow(Matrix[] row){
        Matrix[] result = new Matrix[k];
        for(int i = 0; i < k; ++i){
            Matrix m = Matrix.oneMatrix(k+1);
            for(int j = 0; j < k; ++j){
                m = Matrix.mul(m, row[(i+j)%k]);
            }
            result[i] = m;
        }
        return result;
    }

    public void solve() {

        Matrix[][] matrixes = new Matrix[100][k];

        for(int i = 0; i < k; ++i){
            Matrix m = Matrix.oneMatrix(k + 1);
            matrixes[0][i] = m;
            for(int j = 0; j <= k; ++j){
                m.set(j, i, 1);
            }
        }
        int[] digits = new int[100];
        int index = 0;
        long limit = n;
        digits[index++] = (int) (limit % k);
        for(int row = 1; row < 100; ++row){
            limit /= k;
            if(limit == 0)break;
            digits[index++] = (int) (limit % k);
            matrixes[row] = upRow(matrixes[row-1]);
        }

        Matrix result = Matrix.oneMatrix(k+1);
        int pos = 0;
        while(index-- > 0){
            while(digits[index]-- > 0){
                result = Matrix.mul(result, matrixes[index][pos++%k]);
            }
        }
        Vector vec = new Vector(k+1);
        vec.set(k, 1);
        out.println(Vector.mul(vec, result).sum());

    }

    static int MOD = (int) (1e9+7);

    static public class Matrix {
        int[][] data;

        public Matrix(int size) {
            this.data = new int[size][size];
        }

        Matrix(Matrix other) {
            int size = other.data.length;
            this.data = new int[size][];
            for(int i = 0; i < size; ++i){
                this.data[i] = Arrays.copyOf(other.data[i], size);
            }
        }
        public void set(int row, int column, int value){
            data[row][column] = value;
        }

        public static Matrix oneMatrix(int size){
            Matrix result = new Matrix(size);
            for(int i = 0; i < size; ++i){
                result.data[i][i] = 1;
            }
            return result;
        }

        public static Matrix mul(Matrix left, Matrix right){
            int size = left.data.length;
            assert size == right.data.length;
            Matrix result = new Matrix(size);
            for(int i = 0; i < size; ++i){
                for(int j = 0; j < size; ++j){
                    int val = 0;
                    for(int k = 0; k < size; ++k){
                        val += 1l * left.data[i][k] * right.data[k][j] % MOD;
                        val += MOD;
                        val %= MOD;
                    }
                    result.data[i][j] = val;
                }
            }
            return result;
        }

        static Matrix degree(Matrix matrix, long degree){
            Matrix result = Matrix.oneMatrix(matrix.data.length);
            while(degree > 0){
                if((degree & 1) == 1){
                    result = Matrix.mul(result, matrix);
                }
                result = Matrix.mul(result, result);
                degree >>= 1;
            }
            return result;
        }
    }

    static public class Vector{
        int[] data;

        public Vector(int size) {
            this.data = new int[size];
        }

        Vector(Vector other) {
            this.data = Arrays.copyOf(other.data, other.data.length);
        }

        public void set(int pos, int val){
            data[pos] = val;
        }

        int get(int pos){
            return data[pos];
        }

        public int sum(){
            long sum = 0;
            for(int i : data){
                sum += i;
            }
            sum %= MOD;
            sum += MOD;
            sum %= MOD;
            return (int) sum;
        }

        public static Vector mul(Vector vec, Matrix matrix){
            int size = vec.data.length;
            assert size == matrix.data.length;
            Vector result = new Vector(size);
            for(int i = 0; i < size; ++i){
                int val = 0;
                for(int j = 0; j < size; ++j){
                    val += 1l * vec.data[j] * matrix.data[j][i] % MOD;
                    val += MOD;
                    val %= MOD;
                }
                result.data[i] = val;
            }
            return result;
        }
    }

    static public class Parser{
        Scanner scanner;

        public Parser() {
            scanner = new Scanner(System.in).useLocale(Locale.ENGLISH);
        }

        public Parser(String str) {
            scanner = new Scanner(str).useLocale(Locale.ENGLISH);
        }

        long nextLong(){
            return scanner.nextLong();
        }

        int nextInteger(){
            return scanner.nextInt();
        }

        double nextDouble(){
            return scanner.nextDouble();
        }

        String nextLine(){
            return scanner.nextLine();
        }

        String next(){
            return scanner.next();
        }

        int[] nextIntegers(int count){
            int[] result = new int[count];
            for(int i = 0; i < count; ++i){
                result[i] = nextInteger();
            }
            return result;
        }

        long[] nextLongs(int count){
            long[] result = new long[count];
            for(int i = 0; i < count; ++i){
                result[i] = nextLong();
            }
            return result;
        }

        int[][] nextIntegers(int fields, int count){
            int[][] result = new int[fields][count];
            for(int c = 0; c < count; ++c){
                for(int i = 0; i < fields; ++i){
                    result[i][c] = nextInteger();
                }
            }
            return result;
        }
    }

    void noResult(){
        throw new NoResultException();
    }

    void noResult(String str){
        throw new NoResultException(str);
    }

    void run(){
        try{
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            out = new PrintWriter(outStream);
            solve();
            out.close();
            System.out.print(outStream.toString());
        } catch (NoResultException exc){
            System.out.print(null == exc.response ? noResultMessage : exc.response);
        }
    }

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

    public static class NoResultException extends RuntimeException{
        private String response;

        public NoResultException(String response) {
            this.response = response;
        }

        public NoResultException() {
        }
    }
}

import java.util.*;
import static java.lang.Math.*;

public class E {
    static void p(Object ...args) {System.out.println(Arrays.deepToString(args));}
    static long MOD = 1_000_000_007;

    /*static int score(int a, int k) {
        int ans = 0;
        while( a > 0) {
            ans += a % k;
            a /= k;
        }
        return ans % k;
    }

    public static long slow(int N, int K) {
        long[] V = new long[N+1];
        for (int i = 0; i <= N; i++)
            V[i] = score(i, K);
        long[] dp = new long[N+1];
        for (int i = 0; i <= N; i++) {
            for (int j = 0; j < K; j++) {
                for (int a = i - 1; a >= 0; a--) {
                    if (V[a] == j) {
                        dp[i] += dp[a];
                        break;
                    }
                }
            }
            dp[i] += 1;
            dp[i] %= MOD;
        }
        return dp[N];
    }*/
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        long N = in.nextLong();
        int K = in.nextInt();

        long[][][] M = new long[100][][];
        for (int i = 2; i < M.length; i++)
            M[i] = makeMatrix(K, i);

        /*p("M[2]");
        for (int i = 0; i < M[2].length; i++)
            p(M[2][i]);
        p("M[3]");
        for (int i = 0; i < M[3].length; i++)
            p(M[3][i]);*/

        long[][][] moveBy = new long[100][][];
        long[][][] moveByK = new long[100][][];
        for (int i = 1; i < moveBy.length - 1; i++) {
            long[][] ans = new long[K+1][K+1];
            for (int j = 0; j < ans.length; j++)
                ans[j][j] = 1;
            for (int j = i - 1; j >= 1; j--)
                ans = multiply(ans, moveByK[j]);

            ans = multiply(ans, M[i+1]);
            moveBy[i] = ans;
            moveByK[i] = new long[K+1][K+1];
            for (int j = 0; j <= K; j++)
                moveByK[i][j][j] = 1;
            for (int j = 0; j < K-1; j++)
                moveByK[i] = multiply(moveByK[i], moveBy[i]);
        }
        /*p("moveBy[2]");
        for (int i = 0; i <= K; i++)
            p(moveBy[2][i]);*/

        long at = 0;
        long[][] f = new long[K+1][K+1];
        for (int i = 0; i < f.length; i++)
            f[i][i] = 1;
        //f = multiply(f, M[2]);
        //f = multiply(f, M[3]);
        long temp = N / K;
        for (int i = 1; temp > 0; i++) {
            for (int j = 0; j < temp % K; j++) {
                //p("mult by", i);
                f = multiply(moveBy[i], f);
            }
            temp /= K;
        }
        /*p("f");
        for (int i = 0; i < K+1; i++)
            p(f[i]);*/
        long[] start = new long[K+1];
        for (int i = 0; i < start.length; i++)
            start[i] = (1L<<(i)) % MOD;
        start[K] = 1;

        int position = (int)(N % K);
        p("taking: ", position);
        long ans = 0;
        for (int i = 0; i < start.length; i++)
            ans += (start[i] * f[i][position]) % MOD;
        ans %= MOD;

        /*long a2 = slow((int)N, K);
        if (ans != a2) {
            p(ans, a2);
            throw new RuntimeException();
        }*/
        System.out.println(ans);
    }
    static long[][] makeMatrix(int K, int a) {
        long[][] res = new long[K+1][K+1];

        int[] v = new int[2*K];
        v[2*K-1] = 0;
        for (int i = 2*K-2; i >= 0; i--) {
            if (i == K-1) {
                v[i] = (K + (K-a + v[i+1]) % K) % K;
            } else {
                v[i] = (K + (K-1 + v[i+1]) % K) % K;
            }
        }
        /*if (a == 2 || a == 3) {
            p(a, v);
        }*/
        for (int i = 0; i <= K; i++)
            res[K][i]++;
        for (int c = 0; c < K; c++) {
            for (int i = 0; i < K; i++) {
                boolean found = false;
                for (int j = c - 1 + K; j >= 0; j--) {
                    if (v[j] == i) {
                        found = true;
                        if (j < K) {
                            res[j][c] += 1;
                        } else {
                            for (int b = 0; b <= K; b++)
                                res[b][c] += res[b][j-K];
                        }
                        break;
                    }
                }
                if (!found) {
                    p(c, i, v);
                    throw new RuntimeException();
                }
            }
        }
        return res;
    }
    static long[][] multiply(long[][] A, long[][] B) {
        long[][] res = new long[A.length][A.length];
        for (int r = 0; r < A.length; r++)
            for (int c = 0; c < A.length; c++) {
                for (int i = 0; i < A.length; i++)
                    res[r][c] += (A[r][i] * B[i][c]) % MOD;
                res[r][c] %= MOD;
            }
        return res;
    }
 }

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.StringTokenizer;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
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);
		TaskE solver = new TaskE();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskE {
    static final long MODULO = (long) (1e9 + 7);
    static final long BIG = Long.MAX_VALUE - Long.MAX_VALUE % MODULO;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
        long n = in.nextLong();
        int k = in.nextInt();
        long pk = 1;
        int pow = 0;
        while (pk <= n / k) {
            pk *= k;
            ++pow;
        }
        matrCache = new long[pow + 1][][];
        long at = 0;
        long[] ways = new long[k + 1];
        ways[k] = 1;
        while (at < n) {
            while (at + pk <= n) {
                long[][] matr = getMatr(digitSum(at, k) % k, k, pow);
                ways = mul(matr, ways);
                at += pk;
            }
            pk /= k;
            --pow;
        }
        long res = 0;
        for (long x : ways) res += x;
        res %= MODULO;
        out.println(res);
    }

    long[][][] matrCache;

    private long[][] getMatr(int pre, int k, int pow) {
        long[][] res = matrCache[pow];
        if (res == null) {
            if (pow == 0) {
                res = new long[k + 1][k + 1];
                for (int i = 0; i < k + 1; ++i) ++res[i][i];
                for (int i = 0; i < k + 1; ++i) {
                    ++res[pre][i];
                }
                --res[pre][pre];
            } else {
                res = new long[k + 1][k + 1];
                for (int i = 0; i < k + 1; ++i) ++res[i][i];
                for (int i = 0; i < k; ++i) {
                    res = mul(res, getMatr(i, k, pow - 1));
                }
            }
            matrCache[pow] = res;
        }
        long[][] rotated = new long[k + 1][k + 1];
        for (int i = 0; i <= k; ++i)
            for (int j = 0; j <= k; ++j) {
                int ii = (i == k) ? k : (pre + i) % k;
                int jj = (j == k) ? k : (pre + j) % k;
                rotated[ii][jj] = res[i][j];
            }
        return rotated;
    }

    private long[] mul(long[][] a, long[] b) {
        long[] c = new long[b.length];
        for (int i = 0; i < c.length; ++i) {
            long s = 0;
            for (int j = 0; j < c.length; ++j) {
                s += a[i][j] * b[j];
                if (s < 0) s -= BIG;
            }
            c[i] = s % MODULO;
        }
        return c;
    }

    private long[][] mul(long[][] a, long[][] b) {
        long[][] c = new long[b.length][b.length];
        for (int i = 0; i < c.length; ++i) {
            for (int k = 0; k < c.length; ++k) {
                long s = 0;
                for (int j = 0; j < c.length; ++j) {
                    s += a[i][j] * b[j][k];
                    if (s < 0) s -= BIG;
                }
                c[i][k] = s % MODULO;
            }
        }
        return c;
    }

    private int digitSum(long at, int k) {
        int res = 0;
        while (at > 0) {
            res += at % k;
            at /= k;
        }
        return res;
    }
}

class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream), 32768);
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }

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

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

}


Life in Bertown has become hard. The city has too many roads and the government spends too much to maintain them. There are n junctions and m two way roads, at which one can get from each junction to any other one. The mayor wants to close some roads so that the number of roads left totaled to n - 1 roads and it were still possible to get from each junction to any other one. Besides, the mayor is concerned with the number of dead ends which are the junctions from which only one road goes. There shouldn't be too many or too few junctions. Having discussed the problem, the mayor and his assistants decided that after the roads are closed, the road map should contain exactly k dead ends. Your task is to count the number of different ways of closing the roads at which the following conditions are met:   There are exactly n - 1 roads left.  It is possible to get from each junction to any other one.  There are exactly k dead ends on the resulting map. Two ways are considered different if there is a road that is closed in the first way, and is open in the second one.

The first line contains three integers n, m and k (3 ≤ n ≤ 10, n - 1 ≤ m ≤ n·(n - 1) / 2, 2 ≤ k ≤ n - 1) which represent the number of junctions, roads and dead ends correspondingly. Then follow m lines each containing two different integers v1 and v2 (1 ≤ v1, v2 ≤ n, v1 ≠ v2) which represent the number of junctions connected by another road. There can be no more than one road between every pair of junctions. The junctions are numbered with integers from 1 to n. It is guaranteed that it is possible to get from each junction to any other one along the original roads.

Print a single number — the required number of ways.

import java.util.*;

public class E {
	public static void main(String[] args) {
		Scanner s = new Scanner(System.in);
		int n = s.nextInt(), m = s.nextInt(), k = s.nextInt();
		int[][] a = new int[m][];
		int[][] count = new int[1 << n][1 << n];
		for (int i = 0; i < m; ++i) {
			int u = s.nextInt() - 1, v = s.nextInt() - 1;
			a[i] = new int[] { u, v };
			count[bit(u) | bit(v)][bit(u) | bit(v)] = 1;
		}
		int result = 0;
		for (int used = 0; used < bit(n); ++used) {
			for (int deadends = 0; deadends < bit(n); ++deadends) {
				int c = Integer.bitCount(deadends);
				if (c > 1 && count[used][deadends] > 1) {
					count[used][deadends] /= c;
				}
				if (used == bit(n) - 1 && c == k) {
					result += count[used][deadends];
				}
				for (int i = 0; i < m; ++i) {
					int u = a[i][0], v = a[i][1];
					int ut = used, dt = deadends;
					if (isUsed(u, used) ^ isUsed(v, used)) {
						if (isUsed(u, used)) {
							ut = add(v, ut);
							if (isUsed(u, dt)) {
								dt = remove(u, dt);
							}
							dt = add(v, dt);
						} else {
							ut = add(u, ut);
							if (isUsed(v, dt)) {
								dt = remove(v, dt);
							}
							dt = add(u, dt);
						}
						count[ut][dt] += count[used][deadends];
					}
				}
			}
		}
		System.out.println(result);
	}

	private static int remove(int v, int dt) {
		return dt ^ bit(v);
	}

	private static int add(int u, int dt) {
		return dt | bit(u);
	}

	private static boolean isUsed(int u, int dt) {
		return (dt & bit(u)) > 0;
	}

	private static int bit(int v) {
		return 1 << v;
	}

}

import java.util.Scanner;

public class E {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int k = sc.nextInt();
		int[][]a = new int[n][n];
		int[][]dp = new int[1 << n][1 << n];
		for (int i = 1; i <= m; i++) {
			int v1 = sc.nextInt();
			int v2 = sc.nextInt();
			v1--;
			v2--;
			a[v1][v2] = a[v2][v1] = 1;
			dp[(1 << v1) | (1 << v2)][(1 << v1) | (1 << v2)] = 1;
		}
		for (int mask = 0; mask < (1 << n); mask++) {
			for (int subm = mask; subm != 0; subm = ((subm-1) & mask)) {
				if (dp[mask][subm]==0)
					continue;
				for (int i = 0; i < n; i++) {
					if ((mask & (1 << i)) != 0) {
						for (int j = 0; j < n; j++) {
							if ((mask & (1 << j))==0 && a[i][j]==1) {
								int new_subm = (subm | (1 << j));
								if ((subm & (1 << i)) != 0)
									new_subm ^= (1 << i);
								int q = (1 << n)-(1 << (j+1));
								if ((new_subm & q) != 0)
										continue;
								dp[mask | (1 << j)][new_subm] += dp[mask][subm];
							}
						}
					}
				}
			}
		}
		int ans = 0;
		for (int mask = 0; mask < (1 << n); mask++) {
			if (Integer.bitCount(mask)==k)
				ans += dp[(1 << n)-1][mask];
		}
		System.out.println(ans);
	}

}

/**
 * Created by IntelliJ IDEA.
 * User: Taras_Brzezinsky
 * Date: 9/13/11
 * Time: 5:34 PM
 * To change this template use File | Settings | File Templates.
 */

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.StringTokenizer;

public class TaskE extends Thread {
    public TaskE() {
        this.input = new BufferedReader(new InputStreamReader(System.in));
        this.output = new PrintWriter(System.out);
        this.setPriority(Thread.MAX_PRIORITY);
    }

    static final long doit(int mask, int dead, int n) {
        if ((mask & dead) == 0) {
            cache[mask][dead] = 0;
            return 0;
        }
        if (cache[mask][dead] != -1) {
            return cache[mask][dead];
        }
        long result = 0;
        for (int a = 0; a < n; ++a) {
            if (((mask & (1 << a)) != 0) && ((dead & (1 << a)) != 0)) {
                for (int b = 0; b < n; ++b) {
                    if (g[a][b] && (mask & (1 << b)) != 0) {
                        if (mask == ((1 << a) | (1 << b))) {
                            cache[mask][dead] = ((dead & mask) == mask) ? 1 : 0;
                            return cache[mask][dead];
                        }
                        if ((dead & (1 << b)) == 0) {
                            result += doit(mask ^ (1 << a), dead, n) + doit(mask ^ (1 << a), dead ^ (1 << b), n);
                        }
                    }
                }
                break;
            }
        }
        cache[mask][dead] = result;
        return result;
    }

    private void solve() throws Throwable {
        int n = nextInt(), m = nextInt(), k = nextInt();
        g = new boolean[n][n];
        cache = new long[1 << n][1 << n];
        for (long[] current : cache) {
            Arrays.fill(current, -1);
        }
        Arrays.fill(cache[0], 1);
        for (int i = 0; i < m; ++i) {
            int a = nextInt() - 1, b = nextInt() - 1;
            g[a][b] = g[b][a] = true;
        }
        long ans = 0;
        for (int dead = 0; dead < (1 << n); ++dead) {
            if (Integer.bitCount(dead) == k) {
                ans += doit((1 << n) - 1, dead, n);
            }
        }
        output.println(ans);

    }

    public void run() {
        try {
            solve();
        } catch (Throwable e) {
            System.err.println(e.getMessage());
            e.printStackTrace();
            System.exit(666);
        } finally {
            output.flush();
            output.close();
        }
    }

    public static void main(String[] args) {
        new TaskE().start();
    }

    private int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }

    private long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }

    private double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }

    private String nextToken() throws IOException {
        while (tokens == null || !tokens.hasMoreTokens()) {
            tokens = new StringTokenizer(input.readLine());
        }
        return tokens.nextToken();
    }

    static long[][] cache;
    static boolean[][] g;
    private BufferedReader input;
    private PrintWriter output;
    private StringTokenizer tokens = null;
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

	/**
	 * @param args
	 */
	static int N, M, K;
	static int[] G, log;
	static long[][] DP;
	public static void main(String[] args) {
		DP = new long[1 << 17][13];

		log = new int[1 << 15];
		for(int i = 0; i < 15; i++)
			log[1 << i] = i;

		InputReader r = new InputReader(System.in);

		N = r.nextInt();
		M = r.nextInt();
		K = r.nextInt();

		G = new int[N];

		int id = 1;
		for(int k = 0; k < M; k++){
			int i = r.nextInt() - 1;
			int j = r.nextInt() - 1;

//			G[Math.min(i, j)] |= 1 << Math.max(i, j);
			G[i] |= 1 << j;
			G[j] |= 1 << i;
		}

		for(long[] i : DP)
			Arrays.fill(i, -1);

		long ret = 0;
		for(int next = G[0]; next > 0; next = (next - 1) & G[0]){
//			System.out.println(Integer.toBinaryString(next));
			ret += go(1, next | 1, Integer.bitCount(next) == 1 ? 1 : 0);
		}

		System.out.println(ret);
	}

	private static long go(int done, int reached, int c) {
		if(done == (1 << N) - 1){
			return c == K ? 1 : 0;
		}else{
			if(DP[gen(done, reached)][c] != -1)return DP[gen(done, reached)][c];

			int can = reached & ~done;
			int curr = can & -can;

//			System.out.println(curr + ", " + currI);
			if(curr == 0)return DP[gen(done, reached)][c] = 0;

			int currI = log[curr];

			long ret = 0;

			ret += go(done | 1 << currI, reached, c + 1);
			for(int next = G[currI] & ~reached; next > 0; next = (next - 1) & G[currI] & ~reached){
//				System.out.println(currI + ", " + next);
				ret += go(done | 1 << currI, reached | next, c);
			}

			return DP[gen(done, reached)][c] = ret;
		}
	}

	private static int gen(int done, int reached) {
		int ret = 0;
		for(int itr = 0; itr < N; itr++){
			ret *= 3;
			if((reached & 1) == 0){
//				if((done & 1) == 1)System.out.println("error");
				ret += 0;
			}else{
				if((done & 1) == 0)ret += 1;
				else ret += 2;
			}

			done /= 2;
			reached /= 2;
		}

		return ret;
	}

	private static String print(int m) {
		String ret = Integer.toBinaryString(m);
		while(ret.length() < N)ret = "0" + ret;
		return ret;
	}

	static class InputReader {
		private BufferedReader reader;
		private StringTokenizer tokenizer;

		public InputReader(InputStream stream) {
			reader = new BufferedReader(new InputStreamReader(stream));
			tokenizer = null;
		}

		public String nextLine() {
			try {
				return reader.readLine();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			}
		}

		public String next() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
			return tokenizer.nextToken();
		}

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

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

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

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

public class cfD implements Runnable {
	private final boolean useStandardIO = true;
	private final String inFile = "segments.in";
	private final String outFile = "segments.out";

	int n, m, k;
	int[][] c, aa;

	int dp[][][];
	boolean[][][] was;

	int go(int m1, int m2, int need) {
		if (was[need][m1][m2])
			return dp[need][m1][m2];
		int res = 0;
		int have = Integer.bitCount(m1);
		int cur = Integer.bitCount(m2);
		if (m2 == 0) {
			if (have == need)
				res = 1;
		} else {
			int[] a1 = new int[have], a2 = new int[cur];
			int j = 0;
			for (int i = 0; i < n; ++i)
				if ((m1 & (1 << i)) != 0)
					a1[j++] = i;
			j = 0;
			for (int i = 0; i < n; ++i)
				if ((m2 & (1 << i)) != 0)
					a2[j++] = i;
			int tot = 1;
			for (int i = 0; i < cur; ++i)
				tot *= (have + 1);
			for (int mask = 1; mask < tot; ++mask) {
				int x = mask;
				int taken = 0, takenMask = 0, newLeaves = 0, newMask = 0;
				boolean ok = true;
				for (j = 0; j < cur; ++j) {
					int y = x % (have + 1);
					x /= (have + 1);
					if (y == 0)
						continue;
					--y;
					if (c[a1[y]][a2[j]] == 0) {
						ok = false;
						break;
					}
					if ((takenMask & (1 << y)) == 0) {
						++taken;
						takenMask |= (1 << y);
					}
					++newLeaves;
					newMask |= (1 << a2[j]);
				}
				if (!ok || newMask == 0)
					continue;
				int old = have - taken;
				if (m1 == 1 && newLeaves < 2)
					++old;
				if (need - old >= 0)
					res += go(newMask, m2 ^ newMask, need - old);
			}
		}

		was[need][m1][m2] = true;
		return dp[need][m1][m2] = res;
	}

	private void solve() throws IOException {
		n = nextInt();
		m = nextInt();
		k = nextInt();
		c = new int[n][n];
		for (int i = 0; i < m; ++i) {
			int x = nextInt() - 1, y = nextInt() - 1;
			c[x][y] = c[y][x] = 1;
		}

		dp = new int[k + 1][1 << n][1 << n];
		was = new boolean[k + 1][1 << n][1 << n];
		writer.print(go(1, (1 << n) - 2, k));
	}

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

	BufferedReader reader;
	StringTokenizer tokenizer;
	PrintWriter writer;

	public void run() {
		try {
			Locale.setDefault(Locale.US);
			if (useStandardIO)
				reader = new BufferedReader(new InputStreamReader(System.in));
			else
				reader = new BufferedReader(new FileReader(inFile));
			tokenizer = null;
			if (useStandardIO)
				writer = new PrintWriter(System.out);
			else
				writer = new PrintWriter(new FileWriter(outFile));
			solve();
			reader.close();
			writer.close();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

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

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

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

	BigInteger nextBigInteger() throws IOException {
		return new BigInteger(nextToken());
	}

	String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}
}

import java.util.*;
import java.lang.*;
import java.math.*;
import java.io.*;
import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;

public class P053E{
	Scanner sc=new Scanner(System.in);

	int INF=1<<28;
	double EPS=1e-9;

	int n, m, k;
	int[] u, v;

	void run(){
		n=sc.nextInt();
		m=sc.nextInt();
		k=sc.nextInt();
		u=new int[m];
		v=new int[m];
		for(int i=0; i<m; i++){
			u[i]=sc.nextInt()-1;
			v[i]=sc.nextInt()-1;
		}
		solve();
	}

	void solve(){
		long[][] dp=new long[1<<n][1<<n];
		// dp[s][t]:=「sが連結かつtが葉」の個数

		for(int i=0; i<m; i++){
			dp[(1<<u[i])|(1<<v[i])][(1<<u[i])|(1<<v[i])]=2;
		}
		for(int s=0; s<1<<n; s++){
			int t=s;
			do{
				if(Integer.bitCount(t)>0){
					dp[s][t]/=Integer.bitCount(t);
				}
				for(int i=0; i<m; i++){
					boolean ub=(s>>u[i]&1)==1;
					boolean vb=(s>>v[i]&1)==1;
					if(ub&!vb){
						dp[s|(1<<v[i])][t&~(1<<u[i])|(1<<v[i])]+=dp[s][t];
					}
					if(!ub&vb){
						dp[s|(1<<u[i])][t&~(1<<v[i])|(1<<u[i])]+=dp[s][t];
					}
				}
				t=(t-1)&s;
			}while(t!=s);
		}

		long ans=0;
		int comb=(1<<k)-1;
		for(; comb<1<<n;){
			ans+=dp[(1<<n)-1][comb];
			int x=comb&-comb, y=comb+x;
			comb=((comb&~y)/x>>>1)|y;
		}
		println(ans+"");
	}

	void println(String s){
		System.out.println(s);
	}

	void print(String s){
		System.out.print(s);
	}

	public static void main(String[] args){
		Locale.setDefault(Locale.US);
		new P053E().run();
	}
}

import java.util.*;
import java.lang.*;
import java.math.*;
import java.io.*;
import static java.lang.Math.*;
import static java.util.Arrays.*;
import static java.util.Collections.*;

public class P053E{
	Scanner sc=new Scanner(System.in);

	int INF=1<<28;
	double EPS=1e-9;

	int n, m, k;
	int[] u, v;

	void run(){

		// test();
		n=sc.nextInt();
		m=sc.nextInt();
		k=sc.nextInt();
		// k個が葉になる全域木の個数
		// n<=10
		// m<=50
		u=new int[m];
		v=new int[m];
		for(int i=0; i<m; i++){
			u[i]=sc.nextInt()-1;
			v[i]=sc.nextInt()-1;
		}
		solve();
	}

	void test(){
		n=10;
		m=50;
		m=40;
		k=5;
		u=new int[m];
		v=new int[m];
		for(int i=0; i<m; i++){
			u[i]=(int)(random()*n);
			v[i]=(int)(random()*n);
			for(; v[i]==u[i];){
				v[i]=(int)(random()*n);
			}
			boolean ok=true;
			for(int j=0; j<i; j++){
				ok&=u[i]!=u[j]||v[i]!=v[j];
				ok&=u[i]!=v[j]||v[i]!=u[j];
			}
			if(!ok){
				i--;
				continue;
			}
		}
		solve();
	}

	void solve(){
		long[][] dp=new long[1<<n][1<<n];
		// [s][t]:=sが連結，tが葉，の個数

		for(int i=0; i<n; i++){
			// dp[1<<i][1<<i]=1;
		}
		for(int i=0; i<m; i++){
			dp[(1<<u[i])|(1<<v[i])][(1<<u[i])|(1<<v[i])]=2;
		}
		// dp[1][1]=1;
		for(int s=1; s<1<<n; s++){
			int t=s;
			do{
				if(Integer.bitCount(t)>0){
					dp[s][t]/=Integer.bitCount(t);
				}
				for(int i=0; i<m; i++){
					boolean ub=(s>>u[i]&1)==1;
					boolean vb=(s>>v[i]&1)==1;
					if(ub&!vb){
						dp[s|(1<<v[i])][t&~(1<<u[i])|(1<<v[i])]+=dp[s][t];
					}
					if(!ub&vb){
						dp[s|(1<<u[i])][t&~(1<<v[i])|(1<<u[i])]+=dp[s][t];
					}
				}
				t=(t-1)&s;
			}while(t!=s);
		}
		long ans=0;
		int comb=(1<<k)-1;
		for(; comb<1<<n;){
			ans+=dp[(1<<n)-1][comb];
			int x=comb&-comb, y=comb+x;
			comb=((comb&~y)/x>>>1)|y;
		}
		println(ans+"");
	}

	void println(String s){
		System.out.println(s);
	}

	void print(String s){
		System.out.print(s);
	}

	void debug(Object... os){
		System.err.println(Arrays.deepToString(os));
	}

	public static void main(String[] args){
		Locale.setDefault(Locale.US);
		new P053E().run();
	}
}

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

public class E implements Runnable {

	private void solve() throws IOException {
		int n = nextInt();
		int[][] m = new int[n][n];
		int edges = nextInt();
		int k = nextInt();
		for (int i = 0; i < edges; i++) {
			int u = nextInt() - 1, v = nextInt() - 1;
			m[u][v]++;
			m[v][u]++;
		}
		int[][] d = new int[1 << n][1 << n];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				int mask = (1 << i) | (1 << j);
				d[mask][mask] = m[i][j];
			}
		}
		for (int mask = 1; mask < 1 << n; mask++) {
			if (Integer.bitCount(mask) <= 2)
				continue;
			for (int sub = mask; sub > 0; sub = (sub - 1) & mask) {
				int bit = Integer.numberOfTrailingZeros(sub);
				int mask1 = mask ^ (1 << bit);
				int sub1 = sub ^ (1 << bit);
				for (int i = 0; i < n; i++) {
					if ((mask1 & (1 << i)) != 0 && (sub1 & (1 << i)) == 0) {
						d[mask][sub] += m[bit][i] * d[mask1][sub1 | (1 << i)];
						d[mask][sub] += m[bit][i] * d[mask1][sub1];
					}
				}
			}
		}

		int ans = 0;
		for (int mask = 0; mask < 1 << n; mask++) {
			if (Integer.bitCount(mask) == k) {
				ans += d[(1 << n) - 1][mask];
			}
		}
		out.println(ans);
	}

	public static void main(String[] args) {
		new Thread(new E()).start();
	}

	BufferedReader br;
	StringTokenizer st;
	PrintWriter out;
	boolean eof = false;

	public void run() {
		Locale.setDefault(Locale.US);
		try {
			br = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			solve();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			System.exit(239);
		}
	}

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (Exception e) {
				eof = true;
				return "0";
			}
		}
		return st.nextToken();
	}

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

//package round49;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;

public class E5 {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), m = ni(), K = ni();
		boolean[][] g = new boolean[n][n];
		for(int i = 0;i < m;i++){
			int f = ni()-1, t = ni()-1;
			g[f][t] = g[t][f] = true;
		}
		int[][] dp = new int[1<<n][1<<n];
		for(int i = 0;i < n;i++){
			for(int j = i+1;j < n;j++){
				if(g[i][j]){
					dp[1<<i|1<<j][1<<i|1<<j] = 1;
				}
			}
		}
		for(int i = 0;i < 1<<n;i++){
			if(Integer.bitCount(i) <= 1)continue;
			for(int j = 0;j <= i;j++){
				if((i&j)==j){
					if(Integer.bitCount(i) >= 3 && j > 0)dp[i][j] /= Integer.bitCount(j);
					for(int k = 0;k < n;k++){
						if(i<<31-k>=0){
							for(int l = 0;l < n;l++){
								if(i<<31-l<0 && g[l][k]){
									dp[i|1<<k][j&~(1<<l)|1<<k] += dp[i][j];
								}
							}
						}
					}
				}
			}
		}

		long S = 0;
		for(int j = 0;j < 1<<n;j++){
			if(Integer.bitCount(j) == K){
				S += dp[(1<<n)-1][j];
			}
		}
		out.println(S);
	}

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

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

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

	public int ni()
	{
		try {
			int num = 0;
			boolean minus = false;
			while((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'));
			if(num == '-'){
				num = 0;
				minus = true;
			}else{
				num -= '0';
			}

			while(true){
				int b = is.read();
				if(b >= '0' && b <= '9'){
					num = num * 10 + (b - '0');
				}else{
					return minus ? -num : num;
				}
			}
		} catch (IOException e) {
		}
		return -1;
	}

	public long nl()
	{
		try {
			long num = 0;
			boolean minus = false;
			while((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-'));
			if(num == '-'){
				num = 0;
				minus = true;
			}else{
				num -= '0';
			}

			while(true){
				int b = is.read();
				if(b >= '0' && b <= '9'){
					num = num * 10 + (b - '0');
				}else{
					return minus ? -num : num;
				}
			}
		} catch (IOException e) {
		}
		return -1;
	}

	public String ns()
	{
		try{
			int b = 0;
			StringBuilder sb = new StringBuilder();
			while((b = is.read()) != -1 && (b == '\r' || b == '\n' || b == ' '));
			if(b == -1)return "";
			sb.append((char)b);
			while(true){
				b = is.read();
				if(b == -1)return sb.toString();
				if(b == '\r' || b == '\n' || b == ' ')return sb.toString();
				sb.append((char)b);
			}
		} catch (IOException e) {
		}
		return "";
	}

	public char[] ns(int n)
	{
		char[] buf = new char[n];
		try{
			int b = 0, p = 0;
			while((b = is.read()) != -1 && (b == ' ' || b == '\r' || b == '\n'));
			if(b == -1)return null;
			buf[p++] = (char)b;
			while(p < n){
				b = is.read();
				if(b == -1 || b == ' ' || b == '\r' || b == '\n')break;
				buf[p++] = (char)b;
			}
			return Arrays.copyOf(buf, p);
		} catch (IOException e) {
		}
		return null;
	}

	double nd() { return Double.parseDouble(ns()); }
	boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * Created by IntelliJ IDEA.
 * User: piyushd
 * Date: 1/7/11
 * Time: 12:04 AM
 * To change this template use File | Settings | File Templates.
 */
public class DeadEnds {

	int N, M, K;
	int[][] graph;
	long[][] res;

	long solve(int mask, int leaf, int n, int k){
		if(k < 2) return 0;
		if(res[mask][leaf] != -1) return res[mask][leaf];

		if(n == 2){

			int x = -1, y = -1;
			for(int i = 0; i < N; i++) if((mask & (1<<i)) > 0){
				if(x == -1) x = i; else y = i;
			}

			return res[mask][leaf] = graph[x][y];
		}

		long ans = 0;
		for(int i = 0; i < N; i++){
			if((leaf & (1<<i)) > 0){
				for(int j = 0; j < N; j++){
					if((mask & (1<<j)) > 0 && (leaf & (1<<j)) == 0 && graph[i][j] == 1){
						ans += solve(mask - (1<<i), leaf - (1<<i), n - 1, k - 1);
						ans += solve(mask - (1<<i), leaf - (1<<i) + (1<<j), n - 1, k);
				   	}
			   	}
				break;
			}
		}

		return res[mask][leaf] = ans;
	}

    void run(){
		N = nextInt(); M = nextInt(); K = nextInt();
		graph = new int[N][N];

		int x, y;
		for(int i = 0; i < M; i++){
			x = nextInt() - 1; y = nextInt() - 1;
			graph[x][y] = graph[y][x] = 1;
		}

		int[] bitCount = new int[1<<N];
		for(int i = 0; i < bitCount.length; i++){
			bitCount[i] = bitCount[i>>1];
			if(i % 2 == 1) bitCount[i]++;
		}

		long ret = 0;
		res = new long[1<<N][1<<N];
		for(long[] f : res) Arrays.fill(f, -1);
		for(int i = 0; i < (1<<N); i++){
			if(bitCount[i] == K){
				ret += solve((1<<N) - 1, i, N, K);
			}
		}

		System.out.println(ret);
    }

    int nextInt(){
        try{
            int c = System.in.read();
            if(c == -1) return c;
            while(c != '-' && (c < '0' || '9' < c)){
                c = System.in.read();
                if(c == -1) return c;
            }
            if(c == '-') return -nextInt();
            int res = 0;
            do{
                res *= 10;
                res += c - '0';
                c = System.in.read();
            }while('0' <= c && c <= '9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }

    long nextLong(){
        try{
            int c = System.in.read();
            if(c == -1) return -1;
            while(c != '-' && (c < '0' || '9' < c)){
                c = System.in.read();
                if(c == -1) return -1;
            }
            if(c == '-') return -nextLong();
            long res = 0;
            do{
                res *= 10;
                res += c-'0';
                c = System.in.read();
            }while('0' <= c && c <= '9');
            return res;
        }catch(Exception e){
            return -1;
        }
    }

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

    String next(){
        try{
            StringBuilder res = new StringBuilder("");
            int c = System.in.read();
            while(Character.isWhitespace(c))
                c = System.in.read();
            do{
                res.append((char)c);
            }while(!Character.isWhitespace(c=System.in.read()));
            return res.toString();
        }catch(Exception e){
            return null;
        }
    }

    String nextLine(){
        try{
            StringBuilder res = new StringBuilder("");
            int c = System.in.read();
            while(c == '\r' || c == '\n')
                c = System.in.read();
            do{
                res.append((char)c);
                c = System.in.read();
            }while(c != '\r' && c != '\n');
            return res.toString();
        }catch(Exception e){
            return null;
        }
    }

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

import java.util.*;
//4 6 2
//1 2
//2 3
//3 4
//4 1
//1 3
//2 4

public class E {
	public static void main(String[] args) {
		Scanner s = new Scanner(System.in);
		n = s.nextInt();
		m = s.nextInt();
		k = s.nextInt();
		a = new int[m][];
		for (int i = 0; i < m; ++i) {
			int u = s.nextInt() - 1, v = s.nextInt() - 1;
			a[i] = new int[] { u, v };
		}
		b = new boolean[m];
		System.out.println(f(-1, m));
	}

	static int n, m, k;
	static int[][] a;
	static boolean[] b;

	static int f(int x, int en) {
		if (en == n - 1) {
			int[] cs = new int[n];
			for (int i = 0; i < m; ++i) {
				if (!b[i]) {
					++cs[a[i][0]];
					++cs[a[i][1]];
				}
			}
			int cnt = 0;
			for (int c : cs) {
				if (c == 1) {
					++cnt;
				}
			}
			return cnt == k ? 1 : 0;
		}
		int result = 0;
		for (int i = x + 1; i < m; ++i) {
			if (!b[i]) {
				b[i] = true;
				result += f(i, en - 1);
				b[i] = false;
			}
		}
		return result;
	}

	static int max(int... is) {
		int r = 0;
		for (int i : is)
			r = Math.max(r, i);
		return r;
	}
}

/**
 * Created by IntelliJ IDEA.
 * User: Taras_Brzezinsky
 * Date: 9/13/11
 * Time: 5:34 PM
 * To change this template use File | Settings | File Templates.
 */

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.StringTokenizer;

public class TaskE extends Thread {
    public TaskE() {
        this.input = new BufferedReader(new InputStreamReader(System.in));
        this.output = new PrintWriter(System.out);
        this.setPriority(Thread.MAX_PRIORITY);
    }

    static final long doit(int mask, int dead, int n) {
        if ((mask & dead) == 0) {
            return cache[mask][dead] = 0;
        }
        if (cache[mask][dead] != -1) {
            return cache[mask][dead];
        }
        long result = 0;
        for (int a = 0; a < n; ++a) {
            if ((mask & (1 << a)) == 1 && (dead & (1 << a)) == 1) {
                for (int b = 0; b < n; ++b) {
                    if (g[a][b] && (mask & (1 << b)) != 0) {
                        if (mask == ((1 << a) | (1 << b))) {
                            return cache[mask][dead] = ((dead & mask) == mask) ? 1 : 0;
                        }
                        if ((dead & (1 << b)) == 0) {
                            result += doit(mask ^ (1 << a), dead, n) + doit(mask ^ (1 << a), dead ^ (1 << b), n);
                        }
                    }
                }
            }
        }
        return cache[mask][dead] = result;
    }

    private void solve() throws Throwable {
        int n = nextInt(), m = nextInt(), k = nextInt();
        g = new boolean[n][n];
        cache = new long[1 << n][1 << n];
        for (long[] current : cache) {
            Arrays.fill(current, -1);
        }
        Arrays.fill(cache[0], 1);
        for (int i = 0; i < m; ++i) {
            int a = nextInt() - 1, b = nextInt() - 1;
            g[a][b] = g[b][a] = true;
        }
        long ans = 0;
        for (int dead = 0; dead < (1 << n); ++dead) {
            if (Integer.bitCount(dead) == k) {
                ans += doit((1 << n) - 1, dead, n);
            }
        }
        output.println(ans);

    }

    public void run() {
        try {
            solve();
        } catch (Throwable e) {
            System.err.println(e.getMessage());
            e.printStackTrace();
            System.exit(666);
        } finally {
            output.flush();
            output.close();
        }
    }

    public static void main(String[] args) {
        new TaskE().start();
    }

    private int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }

    private long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }

    private double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }

    private String nextToken() throws IOException {
        while (tokens == null || !tokens.hasMoreTokens()) {
            tokens = new StringTokenizer(input.readLine());
        }
        return tokens.nextToken();
    }

    static long[][] cache;
    static boolean[][] g;
    private BufferedReader input;
    private PrintWriter output;
    private StringTokenizer tokens = null;
}

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

public class cfE implements Runnable {
	private final boolean useStandardIO = true;
	private final String inFile = "segments.in";
	private final String outFile = "segments.out";

	private void solve() throws IOException {
		int n=nextInt();
		int[] a = new int[n], b=new int[n];
		for (int i=0; i<n; ++i){
			a[i]=nextInt();
		}
		for (int i=0; i<n; ++i){
			b[i]=nextInt();
		}
		List<Integer> res=new ArrayList<Integer>();
		for (int i=0; i<n; ++i)
			if (a[i] != b[i]){
				for (int j=i+1; j<n; ++j) if (a[i] == b[j]){
					for (int t=j-1; t>=i; --t) {
						int tmp=b[t]; b[t]=b[t+1]; b[t+1]=tmp;
						res.add(t+1);
					}
					break;
				}
			}
		writer.println(res.size());
		for (int x : res) writer.printf("%d %d\n", x, x+1);
	}

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

	BufferedReader reader;
	StringTokenizer tokenizer;
	PrintWriter writer;

	public void run() {
		try {
			Locale.setDefault(Locale.US);
			if (useStandardIO)
				reader = new BufferedReader(new InputStreamReader(System.in));
			else
				reader = new BufferedReader(new FileReader(inFile));
			tokenizer = null;
			if (useStandardIO)
				writer = new PrintWriter(System.out);
			else
				writer = new PrintWriter(new FileWriter(outFile));
			solve();
			reader.close();
			writer.close();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

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

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

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

	BigInteger nextBigInteger() throws IOException {
		return new BigInteger(nextToken());
	}

	String nextToken() throws IOException {
		while (tokenizer == null || !tokenizer.hasMoreTokens()) {
			tokenizer = new StringTokenizer(reader.readLine());
		}
		return tokenizer.nextToken();
	}
}

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

public class E implements Runnable {

	private void solve() throws IOException {
		int n = nextInt();
		int[][] m = new int[n][n];
		int edges = nextInt();
		int k = nextInt();
		for (int i = 0; i < edges; i++) {
			int u = nextInt() - 1, v = nextInt() - 1;
			m[u][v]++;
			m[v][u]++;
		}

		int[][] d = new int[1 << n][1 << n];
		for (int mask = 1; mask < 1 << n; mask++) {
			if (Integer.bitCount(mask) == 1)
				continue;
			if (Integer.bitCount(mask) == 2) {
				d[mask][mask] = 1;
				continue;
			}
			for (int sub = mask; sub > 0; sub = (sub - 1) & mask) {
				int bit = Integer.numberOfTrailingZeros(sub);
				int mask1 = mask ^ (1 << bit);
				int sub1 = sub ^ (1 << bit);
				for (int i = 0; i < n; i++) {
					if ((mask1 & (1 << i)) != 0 && (sub1 & (1 << i)) == 0) {
						d[mask][sub] += m[bit][i] * d[mask1][sub1 ^ (1 << i)];
						d[mask][sub] += m[bit][i] * d[mask1][sub1];
					}
				}
			}
		}

		int ans = 0;
		for (int mask = 0; mask < 1 << n; mask++) {
			if (Integer.bitCount(mask) == k)
				ans += d[(1 << n) - 1][mask];
		}
		out.println(ans);
	}

	public static void main(String[] args) {
		new Thread(new E()).start();
	}

	BufferedReader br;
	StringTokenizer st;
	PrintWriter out;
	boolean eof = false;

	public void run() {
		Locale.setDefault(Locale.US);
		try {
			br = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
			solve();
			out.close();
		} catch (Throwable e) {
			e.printStackTrace();
			System.exit(239);
		}
	}

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (Exception e) {
				eof = true;
				return "0";
			}
		}
		return st.nextToken();
	}

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

//package round49;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;

public class E {
	Scanner in;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni();
		int m = ni();
		int k = ni();
		long[][] dp = new long[1<<n][1<<n]; // 2 1
		dp[0][0] = 1;
		for(int i = 0;i < m;i++){
			int f = ni() - 1;
			int t = ni() - 1;
			if(f > t){
				int d = f; f = t; t = d;
			}
			for(int j = (1<<n)-1;j >= 0;j--){
				for(int l = (1<<n)-1;l >= j;l--){
					if((l&j) == j){
						int nj = j;
						int nl = l;
						if((l>>f)%2 == 1){
							nj |= 1<<f;
						}else{
							nl |= 1<<f;
						}
						if((l>>t)%2 == 1){
							nj |= 1<<t;
						}else{
							nl |= 1<<t;
						}
						dp[nj][nl] += dp[j][l];
					}
				}
			}
		}

		long sum = 0;
		for(int i = 0;i < 1<<n;i++){
			if(n - Integer.bitCount(i) == k){
				sum += dp[i][(1<<n)-1];
			}
		}
		out.println(sum);
	}

	void run() throws Exception
	{
//		StringBuilder sb = new StringBuilder("10 45 5 ");
//		for(int i = 1;i <= 10;i++){
//			for(int j = i + 1;j <= 10;j++){
//				sb.append(i + " " + j + " ");
//			}
//		}
//		INPUT = sb.toString();

		in = INPUT.isEmpty() ? new Scanner(System.in) : new Scanner(INPUT);
		out = new PrintWriter(System.out);

		solve();
		out.flush();
	}

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

	int ni() { return Integer.parseInt(in.next()); }
	void tr(Object... o) { if(INPUT.length() != 0)System.out.println(Arrays.deepToString(o)); }
}