コード
public class SumOverPermutations {
private final int MOD = (int) 1e9 + 7;
public int findSum(int n) {
if (n == 1) {
return 1;
}
int[][] nCm = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++) {
nCm[i][j] = (j == 0 || j == i) ? 1
: (nCm[i - 1][j - 1] + nCm[i - 1][j]) % MOD;
}
}
long[] oneClosed = new long[n];
long[] bothClosed = new long[n];
oneClosed[0] = bothClosed[0] = 1;
oneClosed[1] = n - 1;
bothClosed[1] = n - 2;
for (int i = 2; i < n; i++) {
for (int j = 0; j < i; j++) {
if (j == 0) {
long add = oneClosed[i - 1];
add = (add * (n - 1)) % MOD;
oneClosed[i] += add;
} else {
long add = bothClosed[j];
add = (add * oneClosed[i - 1 - j]) % MOD;
add = (add * n) % MOD;
add = (add * nCm[i - 1][j]) % MOD;
oneClosed[i] += add;
}
if (j == 0 || j == i - 1) {
long add = bothClosed[i - 1];
add = (add * (n - 1)) % MOD;
bothClosed[i] += add;
} else {
long add = bothClosed[j];
add = (add * bothClosed[i - 1 - j]) % MOD;
add = (add * n) % MOD;
add = (add * nCm[i - 1][j]) % MOD;
bothClosed[i] += add;
}
}
oneClosed[i] %= MOD;
bothClosed[i] %= MOD;
}
long ans = 0;
for (int i = 0; i < n; i++) {
if (i == 0 || i == n - 1) {
long add = oneClosed[n - 1];
add = (add * n) % MOD;
ans += add;
} else {
long add = oneClosed[i];
add = (add * oneClosed[n - 1 - i]) % MOD;
add = (add * n) % MOD;
add = (add * nCm[n - 1][i]) % MOD;
ans += add;
}
ans %= MOD;
}
return (int) ans;
}
}