【gdoi2018 day2】第二题 滑稽子图

题意:

给出一棵树。设\(E\)表示边集,\(V\)表示点集,\(S\)\(V\)的一个子集。

\(f(S)=|(u,v)|(u,v)\in E \ \&\&\ u\in V\ \&\&\ v\in V\)

\(\displaystyle \sum_{S\subseteq V}f(S)^k\)\(998244353\)取模的结果。

$n\leq100000,k\leq 10 $。

\

还是对二项式定理不是很熟悉啊。

处理这类和的\(k\)次方问题经常用到二项式定理。

\[\displaystyle (a+b)^k=\sum_{i=0}^k\binom{k}{i}a^ib^{k-i} \]

于是对于每个\(i\in [0,k]\),我们都维护\(f_{v,i}\)表示\(v\)的子树中\(\displaystyle \sum_{S\subseteq T}f(S)^i\)

转移的时候就\(k^2\)转移就行了。

特别地,我们让\(0^0=1\),方便转移。

当然也可以用斯特林数

\[\displaystyle n^m=\sum_{i=0}^m\begin{Bmatrix}m\\i\end{Bmatrix}\binom{n}{i}i! \]

我们有组合恒等式

\[\displaystyle \binom{a+b}{k}=\sum_{i=0}^k\binom{a}{i}\binom{b}{k-i} \]

然后就可以同样的\(k^2\)

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 100005

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

const ll mod=998244353;
ll ksm(ll t,ll x) {
	ll ans=1;
	for(;x;x>>=1,t=t*t%mod)
		if(x&1) ans=ans*t%mod;
	return ans;
}
int n,m,k;
struct road {
	int to,nxt;
}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}

ll f[N][2][15];
ll g[2][15],H[2][15];
ll c[15][15];

void dfs(int v,int fr) {
	f[v][0][0]=f[v][1][0]=1;
	for(int i=h[v];i;i=s[i].nxt) {
		int to=s[i].to;
		if(to==fr) continue ;
		dfs(to,v);
		memset(g,0,sizeof(g));
		for(int j=0;j<=k;j++) {
			for(int q=0;q<=k-j;q++) {
				(g[0][j+q]+=c[j+q][j]*f[v][0][j]%mod*(f[to][0][q]+f[to][1][q]))%=mod;
				(g[1][j+q]+=c[j+q][j]*f[v][1][j]%mod*f[to][0][q])%=mod;
			}
		}
		memset(H,0,sizeof(H));
		for(int j=0;j<=k;j++) {
			for(int q=0;q<=k-j;q++) {
				(H[1][j+q]+=c[j+q][j]*f[v][1][j]%mod*f[to][1][q])%=mod;
			}
		}
		memcpy(f[v],g,sizeof(g));
		for(int j=k;j>=1;j--) 
			for(int q=0;q<j;q++) (H[1][j]+=c[j][q]*H[1][q])%=mod;
		for(int j=0;j<=k;j++) (f[v][1][j]+=H[1][j])%=mod;
	}
}

int main() {
	n=Get(),m=Get(),k=Get();
	for(int i=0;i<=k;i++)
		for(int j=0;j<=i;j++)
			c[i][j]=(!j||i==j)?1:(c[i-1][j-1]+c[i-1][j])%mod;
	int a,b;
	for(int i=1;i<=m;i++) {
		a=Get(),b=Get();
		add(a,b),add(b,a);
	}
	dfs(1,0);
	cout<<(f[1][0][k]+f[1][1][k])%mod;
	return 0;
}

posted @ 2019-03-12 15:27  hec0411  阅读(197)  评论(0编辑  收藏  举报