记录一些自己做的简单题。
P6478
简单容斥。设 \(f[x][i]\) 表示 \(x\) 为根子树,钦定 \(i\) 对祖孙关系的方案数。
可以用树形背包转移。(顺便给我科普了真正正确的树形背包写法。)
然后可以把根对孩子的贡献加入。
\(f[x][i+1] += f[x][i] \cdot (s-i)\)。
\(s\) 表示子树内与 \(x\) 颜色相反的节点个数。(从剩下的未匹配点中选一个匹配。)
然后恰好的方案数就是 $g[k] = \sum_{i=k}^{m = n/2} (-1)^{i-k} \binom{i}{k}f[1][i] (m-i)!@
这里阶乘表示剩下 \(m-i\) 个点对放任自流。
#include <bits/stdc++.h>
#include <assert.h>
using namespace std;
typedef long long ll;
#define ep emplace_back
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define fin freopen("in.in","r",stdin);
inline int read() {
int x=0, v=1,ch=getchar();
while('0'>ch||ch>'9') {
if(ch=='-') v=0;
ch=getchar();
}while('0'<=ch&&ch<='9') {
x=(x*10)+(ch^'0');
ch=getchar();
}return v?x:-x;
}
const int MAX = 5005,P=998244353;
int n, m;
string a;
vector<int>G[MAX];
int fac[2505],inv[2505];
int siz[MAX], s[2][MAX], gg[MAX] , f[MAX][2505]; // 钦定 x 子树内 i 个事件
void inc(int &x,int y){
x+=y;if(x>=P)x-=P;
}
void dfs(int x,int fa) {
siz[x] = 1, s[a[x]&15][x] = 1;
f[x][0] = 1;
for(int y:G[x]) {
if(y==fa) continue;
dfs(y, x);
for(int i=0;i<=min(m,siz[x]+siz[y]);++i) gg[i] = 0;
for(int i=0;i<=min(m,siz[x]);++i) {
for(int j=0;j<=min(m,siz[y]);++j) {
inc(gg[i+j], 1ll * f[x][i] * f[y][j] % P);
}
}
siz[x]+=siz[y];
for(int i=0;i<=min(m, siz[x]);++i) f[x][i] = gg[i];
s[0][x]+=s[0][y], s[1][x]+=s[1][y];
}
for(int i=min(m, siz[x]+1);i;--i) {
inc(f[x][i], 1ll * f[x][i-1] * max(0, s[( a[x] & 15 )^ 1][x] - i + 1) % P);
}
}
int C(int n,int m){
return 1ll*fac[n]*inv[m]%P*inv[n-m]%P;
}
int qpow(int x,int p){
int ret=1;
for(;p;p>>=1,x=1ll*x*x%P)if(p&1)ret=1ll*ret*x%P;
return ret;
}
signed main() {
n = read();
m = n >> 1;
fac[0]=1;
for(int i=1;i<=m;++i)fac[i]=1ll*fac[i-1]*i%P;
inv[m]=qpow(fac[m],P-2);
for(int i=m;i>=1;--i)inv[i-1]=1ll*inv[i]*i%P;
cin >> a; a = ' ' + a;
for(int i=1;i<n;++i) {
int u,v;
u = read(),v = read();
G[u].ep(v), G[v].ep(u);
}
dfs(1,0);
for(int i=0;i<=m;++i)f[1][i]=1ll*f[1][i]*fac[m-i]%P;
for(int i=0;i<=m;++i) {
int ans=0;
for(int j=i;j<=m;++j){
inc(ans,1ll * ((j-i&1) ? P-1 : 1) * f[1][j] % P * C(j,i) % P);
}
printf("%d\n",ans);
}
return 0;
}
标签:ch,魔术,int,MAX,ret,反演,1ll,炫酷,define
From: https://www.cnblogs.com/Lates/p/16846501.html