首页 > 其他分享 >「Daily OI Round 1」block 题解

「Daily OI Round 1」block 题解

时间:2024-01-22 22:58:52浏览次数:32  
标签:en OI la int 题解 ne 儿子 节点 block

设 \(c_u\) 表示节点 \(u\) 的颜色,\(f_u\) 表示只考虑原树中 \(u\) 的子树中的点、选择点 \(u\) 的方案数。对于儿子 \(v\),可以选择同色儿子节点,也可以跳过这个儿子节点,选择 \(v\) 的与 \(u\) 同色的儿子节点 \(w\),故状态转移方程为:

\[f_u=\prod[c_u=c_v]f_v+\left(\prod[c_u=c_w]f_w+1\right) \]

其中 \(v\) 是 \(u\) 的儿子,\(w\) 是 \(v\) 的儿子。

统计答案时,除了考虑选择的点的最近公共祖先被选择的情况(即 \(\sum f_u\)),还有最近公共祖先没有被选择的情况,也就是说一个节点 \(u\) 的几个儿子节点颜色相同,则可以分别在它们的子树中选择,而不选 \(u\)。设 \(g_{u,c}\) 表示考虑 \(u\) 的子树,不选择 \(u\),选择至少两个颜色为 \(c\) 的儿子节点的方案数,因为要分别减去选择 \(0\) 或 \(1\) 个儿子的情况,所以:

\[g_{u,c}=\left(\prod[c_v=c]f_v+1\right)-\left(\sum[c_v=c]f_v\right)-1 \]

其中 \(v\) 是 \(u\) 的儿子。

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 1e5 + 5, P = 1e9 + 7;

int n, c[N];
int la[N], ne[N * 2], en[N * 2], idx;
LL f[N], g[N], res;

void add(int a, int b)
{
	ne[ ++ idx] = la[a];
	la[a] = idx;
	en[idx] = b;
}
void dp(int u, int fa)
{
	f[u] = 1;
	for(int i = la[u]; i; i = ne[i])
	{
		int v = en[i];
		if(v == fa) continue ;
		dp(v, u);
		
		LL t = 1;
		for(int j = la[v]; j; j = ne[j])
		{
			int w = en[j];
			if(w == u) continue ;
			if(c[w] == c[u]) t = t * (f[w] + 1) % P;
		}
		if(c[v] == c[u]) t = (t + f[v]) % P;
		f[u] = f[u] * t % P;
	}
	for(int i = la[u]; i; i = ne[i])
	{
		int v = en[i];
		if(v == fa) continue ;
		g[c[v]] = g[c[v]] * (f[v] + 1) % P;
	}
	for(int i = la[u]; i; i = ne[i])
	{
		int v = en[i];
		if(v == fa) continue ;
		res = (res + g[c[v]] - 1) % P;
		g[c[v]] = 1;
	}
}

int main()
{
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++ ) scanf("%d", &c[i]);
	for(int i = 1; i < n; i ++ )
	{
		int a, b;
		scanf("%d%d", &a, &b);
		add(a, b), add(b, a);
	}
	add(0, 1);
	for(int i = 1; i <= n; i ++ ) g[i] = 1;
	dp(0, 0);
	printf("%lld\n", res);
	return 0;
}

标签:en,OI,la,int,题解,ne,儿子,节点,block
From: https://www.cnblogs.com/recollect-the-past/p/17981305

相关文章

  • CF1424M Ancient Language 题解
    1.题意描述一本字典中有\(r\)\((1\leqr\leq10^6)\)个单词,单词长度不超过$10^3$,所有字母都是小写英文字母,但字母排序不是按英文字母排序,求所有出现字母的一种排序,如果不存在,输出"IMPOSSIBLE"。2.题目分析由排序规则可知,对于字符串\(s\)和\(t\),\(s\)排在\(t\)......
  • CF618C Constellation 题解
    题意描述给定\(n\)个点(\(n\leq10^5\)),找到三个点满足这三个点不在同一直线上且三个点构成的三角形中不包含其他点,保证所有点不会在同一直线上。题目分析首先必然每一个点都可以作为一组解中的点。不妨其中一个点编号为\(1\)。找一个点作为第二个点,为了使没有点在这条边上,这......
  • CF1036F Relatively Prime Powers 题解
    题目分析对于一个不合法的数\(x(x\ge2)\),设\(x=\prodp_i^{r_i}\),令\(g=\gcd(r_1,r_2,\ldots,r_k)\),则\(x=\left(\prodp_i^{r_i/g}\right)^g\),所以\(x\)是一个正整数的\(g\)次方。所以可以枚举上文的\(g\),把每一类不合法方案排除掉,就是答案。设\(f(i)\)表示\(2\)......
  • AT_arc098_d Donation 题解
    一道在kruskal重构树上DP的题。首先,捐钱比较难想,可以反过来思考倒着走领钱的思路。显然,在第一次经过一个节点的时候领钱是最优的,对于节点\(i\),令\(c_i=\max\{a_i-b_i,0\}\),若当前的钱数是\(v\),到节点\(i\)的条件是\(v\gec_i\),如果不满足则把\(v\)补充到\(c_i\),同......
  • P5618 SDOI2015 道路修建题解
    题目分析虽然数据范围只有\(n\le60000\),但是完全可以直接用线段树做。首先考虑那种状态的图在左边和右边加入节点和边之后可以连通。容易发现,这种图有这两个性质:至少有一条路径,经过最左端和最右端中的点。所有点至少和最左端和最右端的点连通。于是可以划分成以下几种状态......
  • [ARC155C] Even Sum Triplet 题解
    一道大分类讨论。如果有一个可以交换的段包含奇数,那么你可以把所有奇数移到最左边并任意调整相对顺序,然后回到任意一种有一个可以交换的段包含奇数的状态。这种情况,如果偶数的数量为\(2\),这两个偶数是不能交换相对位置的,有至少\(3\)个偶数就能交换偶数间相对位置。所以只需要......
  • P7618 [COCI2011-2012#2] FUNKCIJA 题解
    看起来比较复杂,但实际上是一个树上dp的模型。因为每一重循环都最多有一个依赖,可以转化为树上的父子关系,于是就形成了一个森林。对于非叶子节点,设\(f_{u,i}\)表示第\(u\)循环变量的值是\(i\)时所有直接或间接依赖于它的循环变量(即以它为根的子树除开它的部分)循环次数,对非......
  • 题解-[ABC288D] Range Add Query
    题目:[ABC288D]RangeAddQuery-洛谷|计算机科学教育新生态(luogu.com.cn) 大意:一些数,选一个区间A(L~R),并再选一个区间B(长度k),这个区间B的每个数加减(加负数=减一个数)一个数,最终使得区间A全部数为0举个例(样例)0.   3-11-2201.  0-4-2-220 (-3)2.  ......
  • 2024 蓝桥杯模拟赛 1 (div1) 题解
    A.把字符串小写转换成大写即可#include<bits/stdc++.h>usingnamespacestd;voidsolve(){strings;cin>>s;for(inti=0;i<s.size();i++){if(s[i]>='a'&&s[i]<='z'){s[i]=(char)(s[i]-'a......
  • 2024 省选联测部分题解
    目录目录R15T1树V图R15T2矩阵缺失题目:R15T3.R15T1树V图原题:SNOI2024D1T1.注意到答案肯定是形如每个连通块选一个点组成,把连通块缩起来后令\(dp_{u,x}\)表示连通块\(u\)选\(x\)的方案数,每次合并子树转移即可.因为只有\(n^2\)个合法点对所以时间复杂度......