//with an optim sweep by Pablo : ) import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; import java.util.Arrays; import java.util.function.BinaryOperator; public class FlagsIoanaOpts { private static int N,K,T; private static final long Prime = 1000000007; private static final BinaryOperator SUM_MOD_P = (x,y)->(x+y)%Prime; private static TreeMap oldcounts; private static TreeMap newcounts; private static long nfact; private static long fastexp(long b, long e) { long fe = 1; while (e > 0) { if (e%2 == 1) fe = (fe*b) % Prime; b = (b * b) %Prime; e = e/2; } return fe; } private static void computeall() { //compute unnormalized counts int[] cycles = new int[N+1]; for (int i = 0; i<=N; ++i) cycles[i] = 0; cycles[1] = N; oldcounts = new TreeMap<>(Arrays::compare); oldcounts.put(cycles,(long)1); newcounts = new TreeMap<>(Arrays::compare); for (int i = 0; i entry:oldcounts.entrySet()){ int[] oldcycles = entry.getKey(); long oldcount = entry.getValue(); for (int j = 1; j<=N; ++j) if (oldcycles[j] != 0) { //swap inside one cycle, it breaks the cycle in two long combis = j * oldcycles[j]; long totaladd = combis * oldcount; for (int length1 = 1; length1<=j/2; length1 ++) { cycles = new int[N+1]; System.arraycopy( oldcycles, 0, cycles, 0, N+1); cycles[j]--; cycles[length1]++; cycles[j-length1]++; if (j%2 == 0 && length1 == j/2) newcounts.merge(cycles, (totaladd/2)%Prime,SUM_MOD_P); else newcounts.merge(cycles, totaladd%Prime,SUM_MOD_P); } //swap among same-length cycles, it merges the cycles if (oldcycles[j]>=2) { combis = j * j * oldcycles[j] * (oldcycles[j]-1) / 2; var total = ( combis * oldcount) % Prime; cycles = new int[N+1]; System.arraycopy( oldcycles, 0, cycles, 0, N+1); cycles[j]-=2; cycles[2*j]+=1; newcounts.merge(cycles,total,SUM_MOD_P); } //swap among different-length cycles, it merges the cycles for (int other = j+1; other<=N; other++) if (oldcycles[other]!=0) { combis = j * other * oldcycles[j] * oldcycles[other] ; var total = ( combis * oldcount) % Prime; cycles = new int[N+1]; System.arraycopy( oldcycles, 0, cycles, 0, N+1); cycles[other]--; cycles[j]--; cycles[j+other]++; newcounts.merge(cycles,total,SUM_MOD_P); } } } TreeMap aux = oldcounts; oldcounts = newcounts;newcounts = aux; } //normalize for (Map.Entry entry:oldcounts.entrySet()){ cycles = entry.getKey(); long count = entry.getValue(); for (int i = 1 ; i <=N ; ++i) if (cycles[i] > 0 ) { count = (count * fastexp(i,cycles[i])) %Prime; for (int j = 2; j<=cycles[i]; ++j) count = (count* j) % Prime; } count = (count * fastexp(nfact,Prime-2)) % Prime; entry.setValue(count); } } private static void solve() throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] line = br.readLine().split(" "); N = Integer.parseInt(line[0]); K = Integer.parseInt(line[1]); T = Integer.parseInt(line[2]); nfact = 1; for (int i = 2; i<=N;++i) nfact = (nfact*((long)i)) % Prime; computeall(); int[] perm = new int[N]; int[] cycleArray = new int[N+1]; boolean[] seen = new boolean[N]; for (int i = 0; i