zoukankan      html  css  js  c++  java
  • 【gdoi2018 day2】第二题 滑稽子图

    题意:

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

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

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

    $nleq100000,kleq 10 $。

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

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

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

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

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

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

    当然也可以用斯特林数

    [displaystyle n^m=sum_{i=0}^megin{Bmatrix}m\iend{Bmatrix}inom{n}{i}i! ]

    我们有组合恒等式

    [displaystyle inom{a+b}{k}=sum_{i=0}^kinom{a}{i}inom{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;
    }
    
    
  • 相关阅读:
    算法总结7—多维缩放
    算法总结3—神经网络
    算法总结9—优化
    算法总结8—非负矩阵因式分解
    R语言系列—区间估计
    算法总结2—决策树分类器
    算法总结5&6k最近邻与聚类
    统计,逻辑与智能
    算法总结4—支持向量机
    R语言系列—回归分析
  • 原文地址:https://www.cnblogs.com/hchhch233/p/10516992.html
Copyright © 2011-2022 走看看