首页 > 其他分享 >[ATdp v] Subtree

[ATdp v] Subtree

时间:2023-12-23 16:35:34浏览次数:18  
标签:int sum Subtree fa 1ll ATdp include mod

[ATdp v] Subtree

思路

不难想到令 \(f_u\) 表示 \(u\) 子树内满足条件的答案数。

\[f_{u} = \prod_{v\in son_{u}}(f_v + 1) \]

然后换根求出 \(g\) 表示整棵树里的答案:

\[g_u = (\dfrac{g_{fa}}{f_u + 1} + 1)f_u \]

但是你会发现取模之后不一定有逆元,很尴尬。

所以如果把 \(f_u\) 拿出来,\(g\) 就表示子树外的答案,有转移:

\[g_u = g_{fa} \cdot\dfrac{f_{fa}}{f_u + 1} + 1\\ g_u = g_{fa} \cdot\prod_{v\in son_{fa}\vee v\ne u}(f_v + 1) + 1\\ \]

这样就没有除法了,对 \(fa\) 的儿子进行前/后缀积就得到了 \(O(n)\) 的算法。

// Problem: Subtree
// Author: Moyou
// Copyright (c) 2023 Moyou All rights reserved.
// Date: 2023-12-23 15:16:14

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int N = 1e5 + 10;

int n, f[N], g[N], s[N], mod;
vector<int> G[N];

void dfs(int u, int fa) {
    f[u] = 1;
    for(auto v : G[u]) {
        if(v == fa) continue;
        dfs(v, u);
        f[u] = 1ll * f[u] * (f[v] + 1) % mod;
    }
}
void dfs2(int u, int fa) {
    s[G[u].size()] = 1;
    for(int i = (int)G[u].size() - 1, v; i >= 0; i --) {
        v = G[u][i];
        if(v == fa) s[i] = s[i + 1];
        else s[i] = 1ll * s[i + 1] * (f[v] + 1) % mod;  
    }
    int sum = 1;
    for(int i = 0, v; i < G[u].size(); i ++) {
        v = G[u][i];
        if(v == fa) continue;
        g[v] = 1ll * sum * s[i + 1] % mod * g[u] % mod + 1;
        sum = 1ll * sum * (f[v] + 1) % mod; 
    }
    for(auto v : G[u])
        if(v != fa) dfs2(v, u);
}

signed main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n >> mod;
    for(int i = 1, a, b; i < n; i ++) {
        cin >> a >> b;
        G[a].push_back(b), G[b].push_back(a);
    }
    dfs(1, 1), g[1] = 1, dfs2(1, 1);
    for(int i = 1; i <= n; i ++)
        cout << (1ll * g[i] * f[i] % mod) << '\n';

    return 0;
}

标签:int,sum,Subtree,fa,1ll,ATdp,include,mod
From: https://www.cnblogs.com/MoyouSayuki/p/17923255.html

相关文章

  • DPV Subtree
    题意给定一棵\(n\)个节点的线段树。任意黑白染色,求每个点被染成黑色且黑色点组成连通块的方案数。Sol考虑换根dp,钦定当前点作为根节点。\(f_i\)表示当前子树内的方案数。\(g_i\)表示子树外的方案数。\(f\)的转移显然是\(f_u=\prodf_v+1\)。考虑\(g\)的转移......
  • AtCoder Regular Contest 164 F Subtree Reversi
    洛谷传送门AtCoder传送门非常好题目。发现每个点颜色被反转的次数是固定的,为其深度(根结点深度为\(0\))。于是可以看作是,一放棋子就得到分数。那么先手取偶数层和后手取奇数层都会使先手得分,所以双方的目标都是尽可能多取偶数层的结点。考虑若一开始有偶数层的叶子,那么当前的......
  • Subtree 题解
    Subtree题目大意给定一颗树,你可以选出一些节点,你需要对于每个点求出在强制选这个点的情况下所有选择的点联通的方案数,对给定模数取模。思路分析对于这种求树上每一个点方案数的题目,首先考虑换根DP。强制嵌定树根为\(1\),设\(f_i\)表示在\(i\)的子树中选点,\(i\)强制选,所......
  • git subtree的使用简介
    1、gitsubtree的使用简介gitsubtree是一个Git命令,用于在单个Git仓库中管理多个项目。它允许您将一个项目的子目录作为独立的Git仓库处理,同时仍然保持在主仓库中。这使得在不使用子模块的情况下,更容易地将多个项目组合在一个仓库中。以下是gitsubtree的一些常见用法:添加子树......
  • 关于vcpkg中x-history命令移除后及git subtree的使用问答
    1、现在的版本中已经移除了x-history命令,我该使用什么方式来查看port的历史记录呢如果当前版本的vcpkg中已经移除了x-history命令,您可以使用以下方法查看port的历史记录:使用Git命令:首先,确保您已经安装了Git。然后,在命令行或终端中,导航到vcpkg的安装目录。接下来,使用以下命令......
  • Git 工具 - 子模块: submodule与subtree的使用
    git日常使用中,基本都是一个项目一个Git仓库的形式,那么当我们的代码中碰到了业务级别的需要复用的代码,我们一般怎么做呢?比如:某个工作中的项目需要包含并使用另一个项目。也许是第三方库,或者你独立开发的,用于多个父项目的库。所以需要提取一个公共的类库提供给多个项目使用,但是......
  • LC 572. Subtree of Another Tree
    572.SubtreeofAnotherTree思路与题解这是一道挺有意思的问题,有三种解法,其中第二种是KMP算法的应用。筛法的原理参见204.CountPrimes。解法1:暴力dfs法。直接暴力......
  • 572. Subtree of Another Tree[Easy]
    572.SubtreeofAnotherTreeGiventherootsoftwobinarytreesrootandsubRoot,returntrueifthereisasubtreeofrootwiththesamestructureandnodev......
  • 浅析Git Subtree的原理与实际应用:git subtree是什么、子仓库与仓库共用、共用代码需求
    一、为什么需要使用GitSubtree关于子仓库或者说是仓库共用,git官方推荐的工具是gitsubtree。在实际的项目开发过程中,公共的代码或者模块是必定会出现的,为了不重......
  • 【题解】CF893F Subtree Minimum Query
    那个……令姐……能以成亲为前提……和我交往吗(娇羞)集训完刚好开方舟春活,并且我刚好攒够了给令姐买衣服的石头,这真的是巧合吗?思路各种做法,但是有强化版。首先是naive......