传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3696

【题解】

f[x][i]表示x节点子树,值为i的方案数。

暴力统计理论复杂度$O(nH^2)$。

按子树排序后统计复杂度好像还是错的。。但是能过

明天研究FWT。。

暴力跑了0.8s,FWT跑了3.1s。。。日

FWT也要按深度合并啊。。FWT的介绍在最后

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10, N = 1e5 + 10, H = 512 + 5;
const int mod = 1e9+7;

int n, f[N][H], g[N], par[N];
ll ans[H]; 

int t[N], tn;
inline int cmp(int a, int b) {
    return g[a] < g[b];
}

int head[N], nxt[N], to[N], tot = 0;
inline void add(int u, int v) {
    ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
}

ll ss[H], tt[H]; 

inline void FWT(ll *a, int op, int L) {
    if(op) {
        for (int len=2; len<=L; len<<=1) {
            int m = len >> 1;
            for (ll *p = a; p != a+L; p += len) {
                for (int k=0; k<m; ++k) {
                    ll x = p[k], y = p[k+m];
                    p[k] = (x+y)/2;
                    p[k+m] = (x-y)/2;
                }
            }
        }
    } else {
        for (int len=2; len<=L; len<<=1) {
            int m = len >> 1;
            for (ll *p = a; p != a+L; p += len) {
                for (int k=0; k<m; ++k) {
                    ll x = p[k], y = p[k+m];
                    p[k] = x+y;
                    p[k+m] = x-y;
                }
            }
        }
    }
}

inline void FWT_combine(int *A, int an, int *B, int bn) {
    int L = 0, m = max(an, bn);
    while((1<<L) < m) ++L; m = (1<<L);
     for (int i=0; i<m; ++i) ss[i] = A[i], tt[i] = B[i];
    FWT(ss, 0, m), FWT(tt, 0, m);
    for (int i=0; i<m; ++i) ss[i] = ss[i] * tt[i];
    FWT(ss, 1, m);
    for (int i=0; i<m; ++i) ans[i] += ss[i];
}

inline void dfs(int x) {
    int ret = 1;
    f[x][0] = 1; 
    for (int i=head[x]; i; i=nxt[i]) dfs(to[i]);
    tn = 0; for (int i=head[x]; i; i=nxt[i]) t[++tn] = to[i]; 
    sort(t+1, t+tn+1, cmp);
    for (int i=1; i<=tn; ++i) { 
        int h = g[t[i]], y = t[i];
        FWT_combine(f[x], ret, f[t[i]], h);
        for (int j=0; j<h; ++j) f[x][j] += f[y][j];  
        ret = max(ret, h); 
    }
    for (int j=ret; j; --j) f[x][j] = f[x][j-1];
    f[x][0] = 0; 
    g[x] = ret + 1; 
}


int main() {
    cin >> n;
    for (int i=2; i<=n; ++i) scanf("%d", par+i), add(par[i], i); 
    dfs(1);    
    for (int i=511; ~i; --i)
        if(ans[i] != 0) {
             for (int j=0; j<=i; ++j)
                 printf("%lld\n", ans[j]);
            return 0;
        }
    return 0;
}
View Code

相关文章:

  • 2021-04-06
  • 2021-10-24
  • 2021-07-12
  • 2022-12-23
  • 2022-12-23
  • 2021-08-12
  • 2022-12-23
猜你喜欢
  • 2021-09-08
  • 2022-12-23
  • 2022-12-23
  • 2021-09-26
  • 2021-10-24
  • 2021-12-31
  • 2021-12-03
相关资源
相似解决方案