首页 > 其他分享 >ARC121F Logical Operations on Tree【DP】

ARC121F Logical Operations on Tree【DP】

时间:2023-02-22 22:13:46浏览次数:38  
标签:Operations int text Tree 合法 叶子 1LL DP mod

给定一棵树,给每个点填 \(0\) 或 \(1\),给每条边填 \(\text{AND}\) 或 \(\text{OR}\),求有多少种填法满足存在一种缩边的顺序,使得每次把一条边的两个端点缩成一个点,权为原端点与边的运算值,最终点的权为 \(1\)。答案对 \(998244353\) 取模。

\(n \leq 10^5\)。


不妨钦定 \(1\) 为根。考虑一个特殊的局部:如果在操作过程中,出现了某个叶子的值为 \(1\) 且连接它的边为 \(\text{OR}\),那么只需要将其放在最后操作,就一定能够得到 \(1\)。我们用有序对 \((1, \text{OR})\) 来描述这个叶子的状态。

接着我们考虑出现的叶子的其他状态:

  • \((1,\text{AND})\) 和 \((0,\text{OR})\) :显然这个叶子对答案没有影响,因此原树合法的充要条件是上面的部分合法。

  • \((0,\text{AND})\):由于操作之后其父亲的权会变为 \(0\),我们不妨在这样的叶子出现时就立刻对其进行操作,这样能够减小它对答案的负面影响。因此原树合法的充要条件还是上面的部分合法。

也就是说,如果不存在某种操作方式使得能够出现 \((1, \text{OR})\) 这样的叶子,那么依次删掉叶子一定不劣。此时合法的充要条件是:根节点权为 \(1\),且其儿子形成的叶子的状态都是 \((1,\text{AND})\) 或 \((0,\text{OR})\)。这是相对容易计数的。

考虑容斥,改为计算不合法的方案数。如果我们能求出不存在 \((1,\text{OR})\) 的方案数 \(f\) 和其中合法的方案数 \(g\),那么 \(f-g\) 就是不合法的方案数。考虑树形 DP,设 \(f_u\) 表示 \(u\) 的子树中不存在 \((1,\text{OR})\) 的方案数,\(g_u\) 表示 \(u\) 的子树中不存在 \((1,\text{OR})\) 且合法的方案数。根据上面的分析,初始时 \(f_u = 2,g_u = 1\)。

对于 \(f\),有转移 \(f_u \gets f_u \times \prod \limits_{v \in \text{son}_u} (2 \times f_v - g_v )\)。其中 \(2 \times f_v\) 是因为 \((u,v)\) 可以是 \(\text{OR}\) 或 \(\text{AND}\),减去 \(g_v\) 是为了排除 \(v\) 子树合法且 \((u,v)\) 为 \(\text{OR}\),即出现 \((1,\text{OR})\) 的情况。

对于 \(g\),有转移 \(g_u \gets g_u \times \prod \limits_{v \in \text{son}_u} f_v\)。注意无论 \(v\) 子树是否合法,由于其成为叶子时状态只能是 \((1, \text{AND})\) 或 \((0,\text{OR})\),因此 \((u,v)\) 实际上是确定的,因此 \(f_v\) 的系数为 \(1\)。

时间复杂度 \(O(n)\)。

code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5, mod = 998244353;
int n, f[N], g[N];
vector <int> e[N];
int ksm(int a, int b) {
    int ret = 1;
    while (b) {
        if (b & 1) ret = 1LL * ret * a % mod;
        a = 1LL * a * a % mod, b >>= 1;
    }
    return ret;
}
void dfs(int u, int ff) {
    f[u] = 2, g[u] = 1;
    for (auto v : e[u]) {
        if (v == ff) {
            continue;
        }
        dfs(v, u);
        f[u] = 1LL * f[u] * (1LL * f[v] * 2 % mod + mod - g[v]) % mod;
        g[u] = 1LL * g[u] * f[v] % mod;
    }
}
int main() {
    ios :: sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n;
    for (int i = 1, x, y; i < n; i++) {
        cin >> x >> y;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dfs(1, 0);
    int ans = (1LL * ksm(2, 2 * n - 1) + mod - f[1] + g[1]) % mod;
    cout << ans << "\n";
    return 0;
}

标签:Operations,int,text,Tree,合法,叶子,1LL,DP,mod
From: https://www.cnblogs.com/came11ia/p/17145867.html

相关文章

  • 基于MATLAB的LDPC编译码误码率仿真,仿真调制为64QAM,对比不同译码迭代次数
    1.算法描述LDPC码是麻省理工学院RobertGallager于1963年在博士论文中提出的一种具有稀疏校验矩阵的分组纠错码。几乎适用于所有的信道,因此成为编码界近年来的研究热点。它......
  • UDP协议
    UDP协议概述UDP(UserDatagramProtocol)协议和TCP协议都是传输层协议,UDP仅在IP数据报的基础上增加了两个基本的服务:复用和分用以及差错检测。UDP的优点如下:UDP无需建......
  • ESP8266配置UDP数据传输
    1.ESP8266简介   ESP8266是一款高性能的WIFI串口模块,内部集成MCU能实现单片机之间串口通信,是目前使用最广泛的一种WIFI模块之一。可以简单理解为一个WIFI转串口的设备......
  • 插头 dp
    开一个扫盲计划。oiwiki从左到右把完全不会的看一遍。于是现在来开插头。其实插头如果理解了是个什么东西的话还是比较套路的。不详细讲了,大概可以看洛谷第二篇题解的图......
  • 一键安装wordpress
    #!/bin/bash nginx_souecepwd=/usr/local/nginx#源码安装路径cdnginx_configpwd=/usr/local/nginx/confsystemd_ExecStartpwd=/usr/local/nginx/sbin/nginxif[!-......
  • sourcetree中本地项目提交到远程仓库的具体方法
    转:https://pcedu.pconline.com.cn/1533/15337252.htmlsourcetree中本地项目提交到远程仓库的具体方法2022-08-2516:45 出处:其他 作者:佚名 能否取代智能手机后的新......
  • 【YBT2023寒假Day12 B】仰望星空(DP)(线段树)(笛卡尔树)
    仰望星空题目链接:YBT2023寒假Day12B题目大意有一个n*n的网格,第i列下面的ai个点都是障碍。然后又一些不是障碍的地方有特殊点,删掉它有费用。要你用最小费用使得......
  • SourceTree跳过注册方法
    1,首先下载并安装好git程序。进入登录或注册bitbucket的界面,先别急着操作,继续往下看。2.关闭上述安装窗口,打开%LocalAppData%\Atlassian目录(win+r打开命令模式,把%LocalAp......
  • 内核通用xdp
    目前想做个功能,一些简单转发就在内核中直接转发走,所以想到了XDP,但是呢,部分网卡驱动不支持XDP程序,能不能在netif_recv收包接口或者驱动的hook钩子挂载一个通用接口来处理XD......
  • udp通信
    服务端:importsocketsk=socket.socket(type=socket.SOCK_DGRAM)sk.bind(("127.0.0.1",8080))whileTrue:msg,addr=sk.recvfrom(1024)print(msg.dec......