Permutations II
Solución 1 - DP de componentes conexas
Definimos como el número de configuraciones válidas de los números de a en “componentes conexas”, donde el valor tiene bordes. Por ejemplo, el conjunto de intervalos se contaría en el estado .
- Si no tiene bordes, entonces debe unir dos componentes conexas existentes.
- Si tiene un borde, entonces debe añadirse a una componente conexa existente.
- Si tiene dos bordes, debe insertarse como su propia componente conexa.
Esto corresponde a las siguientes transiciones:
El caso base es , y la respuesta final es .
Implementación
Complejidad temporal:
#include <bits/stdc++.h>
const int MOD = 1000000007;
int main() {
int N;
std::cin >> N;
std::vector dp(N + 1, std::vector<std::array<long long, 3>>(N + 2));
for (auto &a : dp)
for (auto &b : a) b.fill(0);
dp[0][0][0] = 1;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= i; j++) {
dp[i][j][0] =
(j * (j + 1) * dp[i - 1][j + 1][0] + j * j * dp[i - 1][j + 1][1] +
j * (j - 1) * dp[i - 1][j + 1][2]) %
MOD;
dp[i][j][1] = (2 * j * dp[i - 1][j][0] + (2 * j - 1) * dp[i - 1][j][1] +
(2 * j - 2) * dp[i - 1][j][2]) %
MOD;
dp[i][j][2] =
(dp[i - 1][j - 1][0] + dp[i - 1][j - 1][1] + dp[i - 1][j - 1][2]) % MOD;
}
}
std::cout << (dp[N][1][0] + dp[N][1][1] + dp[N][1][2]) % MOD << '\n';
}Solución 2 - OEIS
Haciendo fuerza bruta de los primeros términos y metiendo la secuencia en OEIS se obtiene OEIS - A002464 , que es exactamente lo que buscamos. Esto nos da la recurrencia más simple .
Implementación
Complejidad temporal:
N = int(input())
dp = [0] * (N + 1)
dp[0], dp[1] = 1, 1
for i in range(4, N + 1):
dp[i] = (
(i + 1) * dp[i - 1]
- (i - 2) * dp[i - 2]
- (i - 5) * dp[i - 3]
+ (i - 3) * dp[i - 4]
) % 1000000007
print(dp[N])