AtCoder Regular Contest 102

D - All Your Paths são de Comprimentos Diferentes

Construa um grafo direcionado com no máximo \(20\) vértices e no máximo \(60\) arestas, com pesos de aresta não superiores a \(10^6\), de modo que haja exatamente \(L\) caminhos de \(1\) a \(N\), com comprimentos de \(0\) a \(L-1\).

Como \(2^{20}=1048576\), a ideia natural é usar a representação binária.

Para o maior \(n\) tal que \(2^{n-1}\leq L\), podemos construir com \(n\) vértices um grafo direcionado onde os caminhos de \(1\) a \(n\) têm comprimentos de \(0\) a \(2^{n-1}-1\): considere os vértices \(i=1\sim n-1\)

  • Do vértice \(i\) para \(i+1\) coloque duas arestas, uma com peso \(0\) e outra com peso \(2^{i-1}\).

Seguindo uma abordagem semelhante à DP de dígitos, agora precisamos lidar com a parte maior que \(2^{n-1}\) até \(L\).

Percorrendo os bits de \(L\) do mais significaitvo para o menos, considere cada bit \(1\) de \(L\). Seja \(pre\) a soma dos bits já processados (ou seja, \(2^{n-1}\) mais a soma dos bits \(1\) já tratados). Então, adicione uma aresta do vértice \(i\) para \(n\) com peso \(pre\), repersentando os comprimentos de \(pre+0\) a \(pre+2^{i-1}-1\). Atualize \(pre\) e continue até que o intervalo coberto alcance \(L-1\).

Você pode entender melhor com o código.

//Autor: RingweEH
int L, n, m;

int main() {
    L = read();
    for (n = 1; (1 << n) <= L; n++);
    for (int i = 0; i < n; i++) if (L & (1 << i)) m++;
    printf("%d %d\n", n, m - 1 + 2 * (n - 1));
    for (int i = 1; i < n; i++) 
        printf("%d %d %d\n%d %d %d\n", i, i + 1, 0, i, i + 1, 1 << (i - 1));
    for (int pre = (1 << (n - 1)), i = n; i--; ) 
        if (L & (1 << (i - 1))) 
            printf("%d %d %d\n", i, n, pre), pre += (1 << (i - 1));
    return 0;
}

E - Stop. Caso Contrário...

Temos \(n\) dados, cada um marcado com um número de \(1\) a \(K\). Para cada \(i=2\) a \(2K\), calcule:

  • O número de maneiras (dados não rotulados) em que NÃO existem dois dados cuja soma seja \(i\).

Considere o princípio da inclusão-exclusão. Seja \(cnt\) o número de pares que somam \(x\), e \(f[i]\) o número de maneiras com pelo menos \(i\) pares somando \(x\). A resposta é \(\sum_{i=1}^{cnt} (-1)^i f[i]\). Para calcular \(f[i]\), escolhemos forçadamente \(i\) pares e depois distribuímos o restante livremente:

int main() { k = read(); n = read(); Init(); for (int i = 2; i <= k + k; i++) { int cnt = (s[i] + 1) / 2, ans = 0; for (int j = 0, nw = 1; j <= cnt && j + j <= n; j++, nw = Mod - nw) bmod(ans, 1ll * nw * C(cnt, j) % Mod * C(n - 2 * j + k - 1, k - 1) % Mod); printf("%d\n", ans); } return 0; }


F - A Vingança de BBuBBBlesort!
-------------------------------

Dada uma permutação \\(p\\) de \\(1\\) a \\(n\\), determine se é possível transformá-la em \\(p\[i\]=i\\) usando a seguinte operação:

- Escolha \\(p\[i-1\], p\[i\], p\[i+1\]\\) tais que \\(p\[i-1\] &gt; p\[i\] &gt; p\[i+1\]\\), e troque \\(p\[i-1\]\\) e \\(p\[i+1\]\\).

Inicialmente, um algoritmo ingênuo que processava da esquerda para a direita e depois da direita para a esquerda passou em 2/3 dos casos. /jk

A solução correta é a seguinte:

Seja \\(a\[i\] = \[b\[i\] = i\]\\) (indicador se o elemento está na posição correta). Defina um intervalo como válido se ele for alternado em 0 e 1, começando e terminando com 0.

Observações:

- Uma posição (como centro) se move uma vez e nunca mais se move (considere as relações de ordem).
- Se houver três zeros consecutivos em \\(a\\), não há solução (consequência da observação anterior).

Primeiro, maximize o comprimento de cada sequência válida que contém uma posição. Se todas as sequências válidas satisfizerem simultaneamente as seguintes condições, existe uma solução. Para um intervalo \\(\[l, r\]\\),

- Os valores dos elementos pertencem a \\(\[l, r\]\\).
- Para posições cujo destino está à esquerda: \\(\\forall i&lt;j, a\[i\] &lt; a\[j\]\\).
- Para posições cujo destino está à direita: \\(\\forall i&lt;j, a\[i\] &lt; a\[j\]\\).

</div>

Tags: AtCoder grafo construtivo binário Inclusão-Exclusão

Publicado em 6-1 23:07 por Thomas