首页 > 其他分享 >「解题报告」CF1067E Random Forest Rank

「解题报告」CF1067E Random Forest Rank

时间:2023-03-11 16:33:55浏览次数:58  
标签:匹配 int CF1067E Random Rank 1ll 行列式 ans prob

感觉非常强大。

求秩不好考虑,容易想到求行列式。如果行列式不等于 \(0\) 说明满秩。

先考虑树邻接矩阵的行列式:行列式的定义式即枚举一个排列。排列可以划分成若干个置换环,这相当于要求图上的若干个环。

而考虑到树中没有大小大于等于 \(3\) 的环,只有 \(2\) 的环(一条边),那么树的邻接矩阵的行列式就相当于是求一个完美匹配。而树的完美匹配最多只有一个,所以行列式不等于 \(0\) 当且仅当树存在完美匹配。

考虑秩如何计算:秩等于矩阵中不为零的子式的最大阶数称为矩阵A的秩。子式是指选出若干行列,把交叉处的数留下来形成新的矩阵。

假如我们选出的行列不相等,那么就会出现单向边,而这意味着不可能存在完美匹配。而若我们选出的行列相等,相当于选出一个点集,使得这个点集合的导出子图存在完美匹配。这实际上意味着树的最大匹配。

那么我们就把问题转换成了:对于一颗树,求最大匹配的期望值。

考虑对树求最大匹配的过程:贪心选取,能匹配则匹配。注意到虽然最大匹配不止一种,但是由这种贪心策略得出的最大匹配是唯一的。

那么我们可以完全按照求最大匹配的过程来求概率。根据期望的线性性,最大匹配的期望就是每条边在最大匹配中的概率的和。简单树形 DP 即可。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 500005, P = 998244353, I = (P + 1) / 2;
int n;
int qpow(int a, int b) {
    int ans = 1;
    while (b) {
        if (b & 1) ans = 1ll * ans * a % P;
        a = 1ll * a * a % P;
        b >>= 1;
    }
    return ans;
}
vector<int> e[MAXN];
int f[MAXN][2];
void dfs(int u, int pre) {
    int prob = 1;
    f[u][0] = 1;
    for (int v : e[u]) if (v != pre) {
        dfs(v, u);
        f[u][1] = (f[u][1] + 1ll * prob * I % P * f[v][0]) % P;
        f[u][0] = 1ll * f[u][0] * I % P * (f[v][1] + 1) % P;
        prob = 1ll * prob * I % P * (f[v][1] + 1) % P;
    }
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i < n; i++) {
        int u, v; scanf("%d%d", &u, &v);
        e[u].push_back(v);
        e[v].push_back(u);
    }
    dfs(1, 0);
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        ans = (ans + f[i][1]) % P;
    }
    ans = 1ll * ans * qpow(2, n) % P;
    printf("%d\n", ans);
    return 0;
}

标签:匹配,int,CF1067E,Random,Rank,1ll,行列式,ans,prob
From: https://www.cnblogs.com/apjifengc/p/17206350.html

相关文章

  • CF1067E Random Forest Rank
    非常神秘题。考虑\(\operatorname{rank}A=n\)当且仅当\(\detA\neq0\),我们把\(\detA\)写下来:\[\sum_{p}(-1)^{\pi(p)}\prod_{i=1}^nA_{i,p_i}\]考虑这是......
  • random模块
    1使用==》importrandom#随机小数2用法random.random()  #大于零且小于1的小数 random.uniform(start,stop)==》(start,stop是整数) #大于start小于stop的小数r......
  • 随机模块random
    验证码的实现:choice是选择列表中任意一个##记得把randint取出来的数字转化成str类型,要不就会相加##cha()是把asc编码表里的数字转化成字符更进一步做成函数形式ssample......
  • np.random.normal 正态分布(Normal distribution)
    正态分布(Normaldistribution),也称“常态分布”,又名高斯分布(Gaussiandistribution),最早由棣莫弗(AbrahamdeMoivre)在求二项分布的渐近公式中得到。C.F.高斯在研究测量误差时......
  • Numpy之random.randint产生随机整数
    前言本文主要讲述了如何使用Numpy的random.randint来产生随机整数,我们演示了如何生成不同上限或下限的指定大小的数组方法numpy.random.randint(low,high=None,s......
  • 380. Insert Delete GetRandom O(1)
    380.InsertDeleteGetRandomO(1)标签(空格分隔):leetcodearraymedium题目DesignadatastructurethatsupportsallfollowingoperationsinaverageO(1)......
  • np.random.seed(0)有什么用?
    np.random.seed(0)使随机数可预测>>>numpy.random.seed(0);numpy.random.rand(4)array([0.55,0.72,0.6,0.54])>>>numpy.random.seed(0);numpy.random.ran......
  • R语言随机森林RandomForest、逻辑回归Logisitc预测心脏病数据和可视化分析|附代码数据
    全文链接:http://tecdat.cn/?p=22596最近我们被客户要求撰写关于预测心脏病数据的研究报告,包括一些图形和统计输出。本报告是对心脏研究的机器学习/数据科学调查分析。更......
  • nn.MarginRankingLoss使用详解
    importtorchcriterion=torch.nn.MarginRankingLoss(margin=0.3,reduction='mean')x1=torch.Tensor([3,2])x2=torch.Tensor([1,4])y=torch.Tensor([1,2])......
  • java - Random18
    猜数字案例packagecom.demo.test;importjava.util.Random;importjava.util.Scanner;publicclassrr{publicstaticvoidmain(String[]args){......