ソースコード
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.HashMap;
import java.util.InputMismatchException;
import java.util.List;
import java.util.Map;
public class Main {
static InputStream is;
static PrintWriter out;
static String INPUT = "";
static List<List<Integer>> valids;
static Map<Long, Integer> ids;
static int idgen = 0;
static void dfs(int cur, int P, Deque<Integer> hist)
{
long code = 0;
for(int c : hist){
code = code * 1000000009 + c;
}
valids.add(new ArrayList<>(hist));
ids.put(code, idgen++);
for(int i = 1;i < P;i++){
if((cur&i) == 0){
hist.addLast(i);
dfs(cur|i, P, hist);
hist.pollLast();
}
}
}
static void solve() {
int n = ni(), K = ni(), P = ni();
if(K > 8*n){
out.println(0);
return;
}
if(P >= 257){
throw new RuntimeException();
}
valids = new ArrayList<>();
ids = new HashMap<>();
Deque<Integer> cur = new ArrayDeque<>();
dfs(0, P, cur);
// tr(valids.size());
int mod = 1000000007;
int[][] dp = new int[idgen][K+1];
dp[0][0] = 1;
int[][] to = new int[idgen][P];
for(int j = 0;j < idgen;j++){
List<Integer> h = valids.get(j);
for(int l = 1;l < P;l++){
int from = 0;
for(int i = h.size()-1;i >= 0;i--){
if((h.get(i)&l) != 0){
from = i+1;
break;
}
}
List<Integer> u = new ArrayList<>(h.subList(from, h.size()));
u.add(l);
long code = 0;
for(int c : u){
code = code * 1000000009 + c;
}
int lto = ids.get(code);
to[j][l] = lto;
}
}
for(int i = 0;i < n;i++){
int[][] ndp = new int[idgen][K+1];
for(int j = 0;j < idgen;j++){
for(int k = 0;k <= K;k++){
if(dp[j][k] == 0)continue;
for(int l = 1;l < P;l++){
int llen = valids.get(to[j][l]).size();
if(k+llen <= K){
ndp[to[j][l]][k+llen] += dp[j][k];
if(ndp[to[j][l]][k+llen] >= mod)ndp[to[j][l]][k+llen] -= mod;
}
}
}
}
dp = ndp;
}
long ans = 0;
for(int i = 0;i < idgen;i++){
ans += dp[i][K];
}
out.println(ans%mod);
}
public static void main(String[] args) throws Exception {
long S = System.currentTimeMillis();
is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
out = new PrintWriter(System.out);
solve();
out.flush();
long G = System.currentTimeMillis();
tr(G - S + "ms");
}
private static boolean eof() {
if (lenbuf == -1)
return true;
int lptr = ptrbuf;
while (lptr < lenbuf)
if (!isSpaceChar(inbuf[lptr++]))
return false;
try {
is.mark(1000);
while (true) {
int b = is.read();
if (b == -1) {
is.reset();
return true;
} else if (!isSpaceChar(b)) {
is.reset();
return false;
}
}
} catch (IOException e) {
return true;
}
}
private static byte[] inbuf = new byte[1024];
public static int lenbuf = 0, ptrbuf = 0;
private static 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 static boolean isSpaceChar(int c) {
return !(c >= 33 && c <= 126);
}
private static int skip() {
int b;
while ((b = readByte()) != -1 && isSpaceChar(b))
;
return b;
}
private static double nd() {
return Double.parseDouble(ns());
}
private static char nc() {
return (char) skip();
}
private static 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 static 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 static 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 static int[] na(int n) {
int[] a = new int[n];
for (int i = 0; i < n; i++)
a[i] = ni();
return a;
}
private static 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 static 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 static void tr(Object... o) {
if (INPUT.length() != 0)
System.out.println(Arrays.deepToString(o));
}
}