void partition_function_vec(fmpz * res, long len)
{
    fmpz * tmp;
    long k, n;

    if (len < 1)
        return;

    tmp = _fmpz_vec_init(len);

    tmp[0] = 1L;

    for (n = k = 1; n + 4*k + 2 < len; k += 2)
    {
        tmp[n] = -1L;
        tmp[n + k] = -1L;
        tmp[n + 3*k + 1] = 1L;
        tmp[n + 4*k + 2] = 1L;
        n += 6*k + 5;
    }

    if (n < len) tmp[n] = -1L;
    if (n + k < len) tmp[n + k] = -1L;
    if (n + 3*k + 1 < len) tmp[n + 3*k + 1] = 1L;

    _fmpz_poly_inv_series(res, tmp, len);

    _fmpz_vec_clear(tmp, len);
}
void
_fmpz_poly_revert_series_lagrange(fmpz * Qinv, const fmpz * Q, slong n)
{
    slong i;
    fmpz *R, *S, *T, *tmp;

    if (n <= 2)
    {
        _fmpz_vec_set(Qinv, Q, n);
        return;
    }

    R = _fmpz_vec_init(n - 1);
    S = _fmpz_vec_init(n - 1);
    T = _fmpz_vec_init(n - 1);

    fmpz_zero(Qinv);
    fmpz_set(Qinv + 1, Q + 1);

    _fmpz_poly_inv_series(R, Q + 1, n - 1);
    _fmpz_vec_set(S, R, n - 1);

    for (i = 2; i < n; i++)
    {
        _fmpz_poly_mullow(T, S, n - 1, R, n - 1, n - 1);
        fmpz_divexact_ui(Qinv + i, T + i - 1, i);
        tmp = S; S = T; T = tmp;
    }

    _fmpz_vec_clear(R, n - 1);
    _fmpz_vec_clear(S, n - 1);
    _fmpz_vec_clear(T, n - 1);
}