首先可以把题目转化一下:把树拆成若干条链,每条链的颜色为其所在的树的颜色,然后排放所有的链成环,求使得相邻位置颜色不同的排列方案数。

然后本题分为两个部分:将一棵树分为1~n条不相交的链的方案数;将这些链安排顺序使得不存在两条相邻的链来自同一棵树。

第一部分显然可以O(n2)树形DP,f[i][j][0/1/2]表示i及其子树j条链,i向儿子连出0/1/2条边的方案数,然后直接背包DP即可。看似O(n3)的树形背包DP其实是O(n2)的。证明复杂度:其实DP时只循环到sz[u]/sz[v]即可,然后可以把每个转移视为儿子v内子树的每个节点和节点u内v外节点组成的点对,于是全部DP完就是枚举了所有的点对,复杂度显然O(n2)。

第二部分,考虑n个点的树划分成i条链的方案是f[i],如果不考虑环只考虑链其对应的指数生成函数为Σf[i]i!(Σ(-1)i-jC(i-1,i-j)xj/j!),其中i∈[1,n],j∈[1,i]。拓展到环上,钦定一棵树作为开头,如果该颜色有i条链,则被算了i次,然后其指数生成函数为:Σf[i](i-1)!(Σ(-1)i-jC(i-1,i-j)xj-1/(j-1)!),其中i∈[1,n],j∈[1,i]。减去首尾同色后,生成函数是这样的:Σf[i](i-1)!(Σ(-1)i-jC(i-1,i-j)xj-2/(j-2)!),其中i∈[2,n],j∈[2,i]。然后暴力卷积即可。

#include<bits/stdc++.h>
using namespace std;
const int N=,mod=;
int n,m,sum,ans,fac[N],inv[N],sz[N],f[N][N][],g[N],tmp[N][],dp[][N],b[N];
vector<int>G[N];
int qpow(int a,int b)
{
int ret=;
while(b)
{
if(b&)ret=1ll*ret*a%mod;
a=1ll*a*a%mod,b>>=;
}
return ret;
}
void dfs(int u,int fa)
{
sz[u]=,f[u][][]=;
for(int i=;i<G[u].size();i++)
if(G[u][i]!=fa)
{
int v=G[u][i];
dfs(v,u);
for(int j=;j<=sz[u]+sz[v];j++)tmp[j][]=tmp[j][]=tmp[j][]=;
for(int j=;j<=sz[u];j++)
for(int k=;k<=sz[v];k++)
{
tmp[j+k][]=(tmp[j+k][]+1ll*f[u][j][]*(f[v][k][]+2ll*f[v][k][]+2ll*f[v][k][]))%mod;
tmp[j+k-][]=(tmp[j+k-][]+1ll*f[u][j][]*(f[v][k][]+f[v][k][]))%mod;
tmp[j+k][]=(tmp[j+k][]+1ll*f[u][j][]*(f[v][k][]+2ll*f[v][k][]+2ll*f[v][k][]))%mod;
tmp[j+k-][]=(tmp[j+k-][]+1ll*f[u][j][]*(f[v][k][]+f[v][k][]))%mod;
tmp[j+k][]=(tmp[j+k][]+1ll*f[u][j][]*(f[v][k][]+2ll*f[v][k][]+2ll*f[v][k][]))%mod;
}
sz[u]+=sz[v];
for(int j=;j<=sz[u];j++)f[u][j][]=tmp[j][],f[u][j][]=tmp[j][],f[u][j][]=tmp[j][];
}
}
int C(int a,int b){return a<b?:1ll*fac[a]*inv[b]%mod*inv[a-b]%mod;}
int S(int a,int b){return (!a&&!b)?:1ll*fac[a]*C(a-,a-b)%mod;}
int main()
{
fac[]=;for(int i=;i<=;i++)fac[i]=1ll*fac[i-]*i%mod;
for(int i=;i<=;i++)inv[i]=qpow(fac[i],mod-);
scanf("%d",&m);
dp[][]=;
for(int p=;p<=m;p++)
{
scanf("%d",&n);
for(int i=;i<=n;i++)G[i].clear();
for(int i=,x,y;i<n;i++)scanf("%d%d",&x,&y),G[x].push_back(y),G[y].push_back(x);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
f[i][j][]=f[i][j][]=f[i][j][]=;
dfs(,);
memset(g,,sizeof g);
for(int i=;i<=n;i++)g[i]=(f[][i][]+2ll*f[][i][]+2ll*f[][i][])%mod;
if(p!=m)
{
memset(b,,sizeof b);
for(int j=;j<=n;j++)
if(g[j])for(int k=,t=;k<=j;k++,t=mod-t)
b[j-k]=(b[j-k]+1ll*t*S(j,j-k)%mod*g[j])%mod;
for(int i=;i<=sum;i++)
if(dp[p-][i])for(int j=;j<=n;j++)
dp[p][i+j]=(dp[p][i+j]+1ll*C(i+j,j)*b[j]%mod*dp[p-][i])%mod;
}
else{
memset(b,,sizeof b);
for(int j=;j<=n;j++)
if(g[j])for(int k=,t=;k<j;k++,t=mod-t)
b[j--k]=(b[j--k]+1ll*t*S(j-,j-k-)%mod*g[j])%mod;
for(int i=;i<=sum;i++)
if(dp[p-][i])for(int j=;j<=n;j++)
ans=(ans+1ll*C(i-+j,j)*b[j]%mod*dp[p-][i])%mod;
}
sum+=n;
}
printf("%d",ans);
}

[JSOI2019]神经网络(树形DP+容斥+生成函数)的更多相关文章

  1. P5405-[CTS2019]氪金手游【树形dp,容斥,数学期望】

    前言 话说在\(Loj\)下了个数据发现这题的名字叫\(fgo\) 正题 题目链接:https://www.luogu.com.cn/problem/P5405 题目大意 \(n\)张卡的权值为\(1 ...

  2. HDU - 5977 Garden of Eden (树形dp+容斥)

    题意:一棵树上有n(n<=50000)个结点,结点有k(k<=10)种颜色,问树上总共有多少条包含所有颜色的路径. 我最初的想法是树形状压dp,设dp[u][S]为以结点u为根的包含颜色集 ...

  3. bzoj 4455 [Zjoi2016]小星星 树形dp&容斥

    4455: [Zjoi2016]小星星 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 643  Solved: 391[Submit][Status] ...

  4. [USACO12FEB] 附近的牛 Nearby Cows - 树形dp,容斥

    给你一棵 \(n\) 个点的树,点带权,对于每个节点求出距离它不超过 \(k\) 的所有节点权值和 \(m_i\) 随便定一个根,设\(f[i][j]\)表示只考虑子树,距离为\(j\)的权值和,\( ...

  5. bzoj 3622 DP + 容斥

    LINK 题意:给出n,k,有a,b两种值,a和b间互相配对,求$a>b$的配对组数-b>a的配对组数恰好等于k的情况有多少种. 思路:粗看会想这是道容斥组合题,但关键在于如何得到每个a[ ...

  6. 【BZOJ 4665】 4665: 小w的喜糖 (DP+容斥)

    4665: 小w的喜糖 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 94  Solved: 53 Description 废话不多说,反正小w要发喜 ...

  7. [Luogu P1450] [HAOI2008]硬币购物 背包DP+容斥

    题面 传送门:https://www.luogu.org/problemnew/show/P1450 Solution 这是一道很有意思的在背包里面做容斥的题目. 首先,我们可以很轻松地想到暴力做背包 ...

  8. 5.15 省选模拟赛 容斥 生成函数 dp

    LINK:5.15 T2 个人感觉生成函数更无脑 容斥也好推的样子. 容易想到每次放数和数字的集合无关 所以得到一个dp f[i][j]表示前i个数字 逆序对为j的方案数. 容易得到转移 使用前缀和优 ...

  9. HDU 5838 (状压DP+容斥)

    Problem Mountain 题目大意 给定一张n*m的地图,由 . 和 X 组成.要求给每个点一个1~n*m的数字(每个点不同),使得编号为X的点小于其周围的点,编号为.的点至少大于一个其周围的 ...

随机推荐

  1. vs密匙

    Visual Studio 2019(VS2019) 企业版 Enterprise 激活码:BF8Y8-GN2QH-T84XB-QVY3B-RC4DF Visual Studio 2017(VS201 ...

  2. POJ 1149 网络流 合并建图

    这个题目我敲了一个简单的EK,这不是难点 难点在于建图,按题目的要求 每个猪圈和顾客都建点的话,那也太多了...我看了Edelweiss里面的缩点方法才建好的图,哎,惭愧啊 实际那些猪圈根本不需要单独 ...

  3. Redis高级用法

    第一章 redis初识 1.1 Redis是什么 介绍 开源:早起版本2w3千行 基于键值对的存储系统:字典形式 多种数据结构:字符串,hash,列表,集合,有序集合 高性能,功能丰富 那些公司在用 ...

  4. Tensorflow学习教程------变量

    #coding:utf-8 import tensorflow as tf x = tf.Variable([1,2]) a = tf.constant([3,3]) #增加一个减法op sub = ...

  5. 68.ORM查询条件:date,time,year,week_day等

    1. date: 首先查看数据库中article表的信息,由表中的create_time字段可以看出时间为2020.2.5 打印出查询的结果: <QuerySet []>:但是查询的结果为 ...

  6. Swift 中调试状态下打印日志

    首先我们应该知道Swift中真个程序的入口就是在AppDelegate.swift中.所以在打印日志在 AppDelegate.swift中是这样的 import UIKit @UIApplicati ...

  7. JOIN US | 京东云诚聘技术精英

    清新的办公区域感受自然的气息,温馨的团队为你我放飞青春的理想 上有天文下有地理的阅读区域 各类图书提供借阅 绿植环绕生机勃勃的会客区域洋溢青春 [高级Java工程师] 职位描述: 参与云计算相关平台/ ...

  8. 201612-1 中间数 Java

    思路: 先排序,两个count变量记录.有点暴力 import java.util.Arrays; import java.util.Scanner; public class Main { publ ...

  9. svnkit-常用api

    0.功能列表 svnkit功能列表 1.递归获取指定目录下目录和文件,以树形展示[svn Update] 2.获取指定文件和属性(版本号.作者.日期.文件类型) 3.获取指定文件或目录的历史记录(版本 ...

  10. postman批量接口测试注意事项

    1.使用cvs文件 导入文件后最后行出现\r符号 用文本打开 删除最后一行空白行 2.打印cvs文件中的接口调用的参数 Pre-request Script: var beginDate=data.b ...