with(combinat);

pet_cycleind_symm_invl :=
proc(n)
option remember;

    if n=0 then return 1; fi;
    if n=1 then return a[1] fi;

    expand(1/n*(a[1]*pet_cycleind_symm_invl(n-1)+
                a[2]*pet_cycleind_symm_invl(n-2)));
end;


pet_cycleind_symm :=
proc(n)
local l;
option remember;

    if n=0 then return 1; fi;

    expand(1/n*add(a[l]*pet_cycleind_symm(n-l), l=1..n));
end;

pet_varinto_cind :=
proc(poly, ind)
local subs1, subs2, polyvars, indvars, v, pot, res;

    res := ind;

    polyvars := indets(poly);
    indvars := indets(ind);

    for v in indvars do
        pot := op(1, v);

        subs1 :=
        [seq(polyvars[k]=polyvars[k]^pot,
             k=1..nops(polyvars))];

        subs2 := [v=subs(subs1, poly)];

        res := subs(subs2, res);
    od;

    res;
end;

T1 :=
proc(n, k)
option remember;
local rep, q, gf;

    rep := -1 + mul(1+A[q]+A[q]^2, q=1..n);
    gf := pet_varinto_cind(rep, pet_cycleind_symm_invl(k));
    gf := expand(gf);

    for q to n do
        gf := coeff(gf, A[q], 2);
    od;

    gf;
end;

# sanity check for small arguments of the parameters
ENUM :=
proc(n,k)
option remember;
local mset, allmsets, idx, digits, dix, src, sidx;

    if k=1 then return 1 fi;

    src := [seq(V[q]$2, q=1..n)];
    allmsets := table();

    for idx from k^(2*n) to 2*k^(2*n)-1 do
        digits := convert(idx, `base`, k)[1..2*n];
        if nops(convert(digits, `set`)) = k then
            mset := table([seq(q=1, q=1..k)]);
            for sidx to 2*n do
                dix := digits[sidx] + 1;
                mset[dix] := mset[dix] * src[sidx];
            od;

            allmsets[sort([entries(mset, `nolist`)])] := 1;
        fi;
    od;

    numelems(allmsets);
end;


# best answer to problem
pet_cycleind_pairs :=
n -> expand((1/2*a[1]^2+1/2*a[2])^n);

T2aux :=
proc(n,k)
option remember;
local idx_slots, idx_colors, res, term_a, term_b,
    v_a, v_b, inst_a, inst_b, len_a, len_b, p, q;

    if k = 1 then return 1 fi;

    idx_slots := pet_cycleind_pairs(n);
    idx_colors := pet_cycleind_symm(k);

    res := 0;

    for term_a in idx_slots do
        for term_b in idx_colors do
            p := 1;

            for v_a in indets(term_a) do
                len_a := op(1, v_a);
                inst_a := degree(term_a, v_a);

                q := 0;

                for v_b in indets(term_b) do
                    len_b := op(1, v_b);
                    inst_b := degree(term_b, v_b);

                    if len_a mod len_b = 0 then
                        q := q + len_b*inst_b;
                    fi;
                od;

                p := p*q^inst_a;
            od;

            res := res +
            lcoeff(term_a)*lcoeff(term_b)*p;
        od;
    od;

    res;
end;

T2 :=
proc(n,k)
    if k=1 then return 1 fi;
    T2aux(n,k)-T2aux(n,k-1);
end;