bzoj5119
考慮任一長度為$n-2$的序列,序列中每個數權值為$[1,n]$,這個序列($prufer$序列)唯一對應一棵形態確定的$n$個節點的樹,反之亦然,即樹和$prufer$序列是雙射關係。
那麼可以將問題轉化為列舉$prufer$序列:$$\beginans&=\sum_d_i=n-2}\frac(\prod_ia_i^(d_i+1)^m)*(\sum_i(d_i+1)^m)\\&=(n-2)!*(\prod_ia_i)*(\sum_d_i=n-2}(\prod_i\frac(d_i+1)^m})*(\sum_i(d_i+1)^m))\\&=(n-2)!*(\prod_ia_i)*(\sum_d_i=n-2}\sum_i((d_i+1)^m*\prod_j\frac(d_j+1)^m}))\\&=(n-2)!*(\prod_ia_i)*(\sum_d_i=n-2}\sum_i(\frac(d_i+1)^}*\prod_\frac(d_j+1)^m}))\\\end$$
設$$a(x)=\sum_^\frac}x^i\\ b(x)=\sum_^\frac}x^i\\ f(x)=\sum_ia(a_ix)\prod_b(a_jx)$$
對$f(x)$化簡:$$\beginf(x)&=\sum_ia(a_ix)\prod_b(a_jx)\\&=(\sum_i\frac)*\prod_ib(a_ix)\\&=(\sum_i\frac)*\exp(\ln(\prod_ib(a_ix)))\\&=(\sum_i\frac)*\exp(\sum_i\ln(b(a_ix)))\end$$
再設$$c(x)=\frac\\ d(x)=\ln(b(x))$$
有:$$[x^j](\sum_i\ln(b(a_ix))) = ([x^j]d(x))*\sum_ia_i^j\\ ([x^j]\sum_\frac)=([x^j]c(x))*\sum_ia_i^j$$
求出$c(x)$與$d(x)$,對它們的第$i$項乘以$\sum_ja_j^i$,也就是需要求數列的$i$次方和,我在生成函式小結裡有寫,這裡就不展開說了。
最終答案:$$ans=(n-2)!*(\prod_ia_i)*[x^]f(x)$$
$o(n\log^2 n)$
#include#includeview code#include
#include
#include
#define ls (x << 1)
#define rs ((x << 1) | 1)
using
namespace
std;
typedef
long
long
ll;const
int maxn = 60005, mod = 998244353, g = 3
;int add(int x, int
y)int rdc(int x, int
y)ll qpow(ll x,
inty)
return
ret;
}int n, m, lim, bit, rev[maxn<<1
], a[maxn];
ll ginv, fac[maxn], fnv[maxn], inv[maxn];
ll a[maxn
<<1], b[maxn<<1], c[maxn<<1], d[maxn<<1], ln[maxn<<1], iv[maxn<<1], f[maxn<<1], h[maxn<<1
];vector
g[maxn<<1
];void
init()
}void ntt_init(int
x)
for(int i = 1; i < lim; ++i)
rev[i] = (rev[i>>1] >> 1) | ((i & 1) << (bit - 1
));}
void ntt(ll *x, int
y) }
}if(y == -1
)
}void get_inv(ll *x, ll *y, int
len)
get_inv(x, y, (len + 1) >> 1
);
for(int i = 0; i < len; ++i)
c[i] =y[i];
ntt_init(len
<< 1
); ntt(x, 1);
ntt(c, 1);
for(int i = 0; i < lim; ++i)
ntt(x, -1
);
for(int i = len; i < lim; ++i)
x[i] = 0;}
void get_ln(ll *x, ll *y, int
len)
ntt(x, -1
);
for(int i = len - 1; i >= 1; --i)
x[i] = x[i-1] * inv[i] %mod;
x[0] = 0
;
for(int i = len; i < lim; ++i)
x[i] = 0;}
void get_exp(ll *x, ll *y, int
len)
get_exp(x, y, (len + 1) >> 1
); get_ln(ln, x, len);
for(int i = 0; i < len; ++i)
ntt_init(len
<< 1
); ntt(x, 1);
ntt(c, 1);
for(int i = 0; i < lim; ++i)
ntt(x, -1
);
for(int i = len; i < lim; ++i)
x[i] = 0;}
void solve(int x, int l, int r, int *y)
int mid = (l + r) >> 1
; solve(ls, l, mid, y);
solve(rs, mid + 1
, r, y);
for(int i = 0; i <= mid - l + 1; ++i)
c[i] =g[ls][i];
for(int i = 0; i <= r - mid; ++i)
d[i] =g[rs][i];
ntt_init(r - l + 1
); ntt(c, 1);
ntt(d, 1);
for(int i = 0; i < lim; ++i)
ntt(c, -1
);
for(int i = 0; i <= r - l + 1; ++i)
for(int i = r - l + 2; i < lim; ++i)
c[i] = 0;}
intmain()
solve(
1, 1
, n, a);
for(int i = 0; i <= n; ++i)
d[i] = g[1
][i];
get_ln(f, d, n + 1
);
for(int i = n; i >= 1; --i)
f[0] =n;
ll tmp;
for(int i = 0; i <= n; ++i)
get_ln(d, b, n + 1
); get_inv(h, b, n + 1
); ntt_init(n
<< 1
); ntt(a, 1);
ntt(h, 1);
for(int i = 0; i < lim; ++i)
a[i] = a[i] * h[i] %mod;
ntt(a, -1
);
for(int i = 0; i <= n; ++i)
for(int i = n + 1; i < lim; ++i)
a[i] = 0
; memset(b,
0, sizeof
(b));
get_exp(b, d, n + 1
); ntt_init(n
<< 1
); ntt(a, 1);
ntt(b, 1);
for(int i = 0; i < lim; ++i)
a[i] = a[i] * b[i] %mod;
ntt(a, -1
); printf(
"%lld
", ans * a[n-2] %mod);
return0;
}
清華集訓2017 生成樹計數
在乙個 s 個點的圖中,存在 s n 條邊,使圖中形成了 n 個連通塊,第 i 個連通塊中有 a i 個點。現在我們需要再連線 n 1 條邊,使該圖變成一棵樹。對一種連邊方案,設原圖中第 i 個連通塊連出了 d i 條邊,那麼這棵樹 t 的價值為 mathrm t left prod m right...
uva 10766 生成樹計數
給出n,m,k,代表一家公司有n個部門,編號1到n,有m組關係,表示i和j不能直接聯通,k代表主管部門,問你有多少種分層方案。這道題的k沒有什麼用。include include include include include include include include include incl...
uva10766生成樹計數
此類題是給定乙個無向圖,求所有生成樹的個數,生成樹計數要用到matrix tree定理 kirchhoff矩陣 樹定理 g的度數矩陣d g 是乙個n n的矩陣,並且滿足 當i j時,dij 0 當i j時,dij等於vi的度數 g的鄰接矩陣a g 也是乙個n n的矩陣,並且滿足 如果vi vj之間有...