WC2019 数树

Task 0

判断有多少条相同边即可。

复杂度\(O(N)\)

namespace Subtask1{
    pair e1[N],e2[N];
    void Main(int n,int y){
        for(int i=1,u,v;i (min(u,v), max(u,v));
        }
        for(int i=1,u,v;i (min(u,v), max(u,v));
        }
        sort(e1+1,e1+n),sort(e2+1,e2+n);
        int j = 1,B = n;
        for(int i=1;i

Task 1

考虑prufer序列,如果硬点了一些边一定被重复覆盖,那么硬点这\(c\)个联通块的方案是:
\[ n^{c-2} \prod siz_i \]
考虑系数,硬点了\(a\)条边会在硬点\(b\)条边中出现了\(\binom{a}{b}\)次,恰好\(a\)条边的贡献是\(y^{n-a}\)

考虑:
\[ \sum _i\binom {A}{i} x^i = (x+1)^A \]
那么系数设置为\(y^{-1}-1\)时,正好会贡献\(y^{-A}\)

\(siz\)的贡献拆组合意义,即:每个连通块内都要选一个节点作为代表。

\(f[x][0/1]\)表示当前节点所在连通块是否选了代表。

复杂度$O(n) $

namespace Subtask2{
    int hed[N],to[N<<1],nxt[N<<1],cnt;
    inline void adde(int u,int v){++cnt;to[cnt]=v,nxt[cnt]=hed[u];hed[u]=cnt;}
    int f[N][2],Val;
    inline void dfs(int x,int pre){
        f[x][1] = n, f[x][0] = 1;
        for(int i=hed[x];i;i=nxt[i]){
            int v=to[i];if(v==pre)continue;
            dfs(v,x);int f1=0,f0=0;
            f1 = add(mul(f[x][1], add(mul(Val,f[v][0]),f[v][1])), mul(mul(Val, f[x][0]), f[v][1]));
            f0 = mul(f[x][0], add(mul(Val, f[v][0]),f[v][1]));
            f[x][1] = f1, f[x][0] = f0;
        }
    }

    void Main(int n,int y){
        for(int i=1,u,v;i

Task 2

容斥系数和以上一样,\(f[i]\)表示\(i\)个点的连通块的贡献。现在要枚举的树是两颗树,所以方案的贡献要平方。

写成\(EGF\)之后\(exp\)就行了。

\(O(n\log n)\)

namespace Subtask3{
    using namespace Template_Poly;
    Poly f;
    int ifac[N], fac[N], Val;
    inline void init(int n = 1e5){
        fac[0] = ifac[0] = 1;for(int i=1;i<=n;i++)fac[i] = mul(fac[i-1], i);
        ifac[n] = qpow(fac[n], mod-2);for(int i=n-1;i;i--)ifac[i] = mul(ifac[i+1], i+1);
    }
    inline void initf(int n){
        f.resize(n+1);
        for(int i=1,w = 1;i<=n;i++, w = mul(w, Val)){
            f[i] = w;f[i] = mul(f[i], mul(qpow(i,max(0,i-2)), 1ll*n*n%mod));
            f[i] = mul(f[i], 1ll*i*i%mod);
            f[i] = mul(f[i], ifac[i]);
        }
    }
    void Main(int n,int y){
        Val = sub(qpow(y,mod-2),1);
        init();initf(n);
        f = exp(f);
        int ans = mul(f[n],fac[n]);
        ans = mul(ans, qpow(1ll*n*n%mod*n%mod*n%mod,mod-2));
        ans = mul(ans, qpow(y,n));
        cout << ans << endl;
    }
}

你可能感兴趣的:(WC2019 数树)