「模拟赛20180406」膜树 prufer编码+概率

题目描述

给定一个完全图,保证\(w_{u,v}=w_{v,u}\)且\(w_{u,u}=0\),等概率选取一个随机生成树,对于每一对\((u,v)\),求\(dis(u,v)\)的期望值对\(998244353\)取模。

输入

第一行一个数\(n\)

接下来\(n\)行,每行\(n\)个整数,第\(i\)行第\(j\)个整数表示\(w_{i,j}\)

输出

输出共\(n\)行,每行\(n\)个整数,第\(i\)行第\(j\)个整数表示\(dis(i,j)\)的期望值

样例

样例输入

4
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0

样例输出

0 374341634 374341634 374341634
374341634 0 374341634 374341634
374341634 374341634 0 374341634
374341634 374341634 374341634 0

数据范围

\(\left|w_{i,j}\right| \leq?10^9\)

\(n?\leq?1000\)

题解

这是一道神奇的概率题……

其实题目原来是有一个\(20%\)的数据点,此时\(n\leq 9\),显然我们可以用\(prufer\)编码枚举生成树,然后暴力算答案即可(\(QwQ\)卡常拿了\(15pts\)走人)。但是显然\(1000\)是不可能的……

于是我们考虑这道题的特殊性质——这是一个完全图!完全图拥有非常好的对称性!
根据上面这点,对于点对\((u,v)\),任意的一条边\((x,y)\)出现在\(u\)到\(v\)的路径上的概率是一样的,同理,任意一条边\((u,x)\)或\((x,v)\)出现在\(u\)到\(v\)的路径上的概率也是一样的。于是我们发现可以把边分成三类。

  1. \((u,v)\),即两端点都在路径上
  2. \((u,x)\)或\((x,v)\),即有一个端点在路径上
  3. \((x,y)\),即两端点都不在路径上

对于第一种,只要这条边出现在生成树中就一定会经过,于是就是某一条边出现在生成树中的概率。生成树有\(n^{n-2}\)种,每种会给\((n-1)\)条边带来\(1\)贡献,显然每条边的总贡献是相同的,于是单条边的贡献为\(\frac{n^{n-2}\cdot(n-1)}{\frac{n\cdot(n-1)}{2}}=2\cdot n^{n-3}\)
然后只需再除以总方案数\(n^{n-2}\)就是概率,即\(\frac{2}{n}\)

考虑第二种,显然对于所有的\((u,x)\)概率都相等……可以发现,如果\((u,v)\)存在生成树中,一定不会选到\((u,x)\),否则就等概率地选中\((u,x)\)。那么答案为\(\frac{1-\frac{2}{n}}{n-2}\)

第三种不容易看出什么特征了,我们暴力一点求。假设把这条边切断,发现左右分成两部分,我们可以枚举其中\(x\)部分的大小,设为\(i\),则\(y\)部分为\(n-i\),其中有\(4\)个点已经确定了——\(x,y,u,v\),为了方便,我们固定\(u\)在\(x\)这边,而\(v\)在\(y\)这边,最后答案乘\(2\)即可(交换\(u,v\))。显然,答案需要乘上\(C_{n-4}^{i-2}\),\(n-4\)是因为除去这四个点,\(i-2\)是除去\(x\)和\(u\)。然后左右两边的任意一个无根树形态都是可以的,根据\(prufer\)编码,答案就是: \[\sum_{i=2}^{n-2}{\cfrac{2\cdot i^{i-2}\cdot(n-i)^{n-i-2}\cdot C^{n-4}_{i-2}}{n^{n-2}}}\]直接\(O(n\log n)\)求就好了

然后统计答案,注意各种小细节,这道题就\(A\)掉辣!

\(Code:\)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 1005
#define mod 998244353
int n, dis[N][N], nei[N], all;
int fir, sec, thi;
int fac[N], inv[N];
int ksm(int a, int k)
{
    if (!k)
        return 1;
    int p = ksm(a, k / 2);
    if (k & 1)
        return 1ll * a * p % mod * p % mod;
    return 1ll * p * p % mod;
}
int div(int a){return ksm(a, mod - 2);}
int tree(int a)
{
    if (a == 1)
        return 1;
    return ksm(a,  a - 2);
}
int C(int n, int m)
{
    return 1ll * fac[n] * inv[m] % mod * inv[n - m] % mod;
}
int main()
{
    fac[0] = 1;
    for (int i = 1; i <= N - 5; i++)
        fac[i] = 1ll * fac[i - 1] * i % mod;
    inv[N - 5] = ksm(fac[N - 5], mod - 2);
    for (int i = N - 5; i >= 1; i--)
        inv[i - 1] = 1ll * inv[i] * i % mod;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
        {
            scanf("%d", &dis[i][j]);
            if (i < j)
                all = (all + dis[i][j]) % mod;
            nei[i] = (nei[i] + dis[i][j]) % mod;
        }
    fir = 2 * div(n) % mod;
    sec = 1ll * (1 - fir) * div(n - 2) % mod;
    if (sec < 0)
        sec += mod;
    for (int i = 1; i < n - 2; i++)
    {
        int j = n - 2 - i;
        thi = (thi + 2ll * tree(i + 1) * tree(j + 1) % mod * C(n - 4, i - 1) % mod) % mod;
    }
    thi = 1ll * thi * div(tree(n)) % mod;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
        {
            int ans = 1ll * dis[i][j] * fir % mod;
            ans = (ans + 1ll * ((nei[i] + nei[j]) % mod - dis[i][j] * 2) % mod * sec % mod) % mod;
            ans = (ans + 1ll * (all - ((nei[i] + nei[j]) % mod - dis[i][j]) % mod) * thi % mod) % mod;
            if (ans < 0)
                ans += mod;
            if (i == j)
                ans = 0;
            printf("%d%c", ans, j == n ? 10 : 32);
        }
}

原文地址:https://www.cnblogs.com/ModestStarlight/p/8728251.html

时间: 2024-10-10 03:49:30

「模拟赛20180406」膜树 prufer编码+概率的相关文章

「模拟赛20191019」B 容斥原理+DP计数

题目描述 将\(n\times n\)的网格黑白染色,使得不存在任意一行.任意一列.任意一条大对角线的所有格子同色,求方案数对\(998244353\)取模的结果. 输入 一行一个整数\(n\). 输出 一行一个整数表示答案对\(998244353\)取模的值. 样例 样例输入 3 样例输出 32 数据范围 对于\(100\%\)的数据,\(1\leq n\leq 300\). 比第一题难了不知道多少-- 这种东西怎么看都是容斥嘛. 我们先考虑对角线没有限制的情况: 枚举行和列有多少个是同色的,

loj #535. 「LibreOJ Round #6」花火 树状数组求逆序对+主席树二维数点+整体二分

$ \color{#0066ff}{ 题目描述 }$ 「Hanabi, hanabi--」 一听说祭典上没有烟火,Karen 一脸沮丧. 「有的哦-- 虽然比不上大型烟花就是了.」 还好 Shinobu 早有准备,Alice.Ayaya.Karen.Shinobu.Yoko 五人又能继续愉快地玩耍啦! 「噢--!不是有放上天的烟花嘛!」Karen 兴奋地喊道. 「啊等等--」Yoko 惊呼.Karen 手持点燃引信的烟花,「嗯??」 Yoko 最希望见到的是排列优美的烟火,当然不会放过这个机会-

【Foreign】树 [prufer编码][DP]

树 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output Sample Input 3 2 2 1 Sample Output 3 3 2 HINT Source 由于是带标号的无根树的计数,于是我们运用prufer编码的性质来解题. prufer编码的几个性质: 1.对于大小为s的树,prufer编码是一个长度为 s-2 的序列: 2.i在序列中出现的次数<deg[i]: 3.一个prufer编码表示一棵树. 所以这

FJoi2017 1月20日模拟赛 直线斯坦纳树(暴力+最小生成树+骗分+人工构造+随机乱搞)

[题目描述] 给定二维平面上n个整点,求该图的一个直线斯坦纳树,使得树的边长度总和尽量小. 直线斯坦纳树:使所有给定的点连通的树,所有边必须平行于坐标轴,允许在给定点外增加额外的中间节点. 如下图所示为两种直线斯坦纳树的生成方案,蓝色点为给定的点,红色点为中间节点. [输入格式] 第一行一个整数n,表示点数. 以下n行,每行两个整数表示点的x,y坐标. [输出格式] 第一行一个整数m,表示中间节点的个数. 必须满足m <= 10 * n 以下m行,每行2个整数表示中间节点的坐标. 以下n+m-1

noip模拟赛 蒜头君的树

分析:这道题问的是树上整体的答案,当然要从整体上去考虑. 一条边对答案的贡献是这条边一端连接的点的个数*另一端连接的点的个数*边权,可以用一次dfs来统计答案,之后每次更改操作在原答案的基础上增减就好了. 千万不要傻傻地去求LCA......事实证明只有10分.问的是任意两点最短距离之和,树上两个点的最短路径只有一条,所以才要去考虑每条边的贡献的. #include <cstdio> #include <cstring> #include <iostream> #inc

「模拟8.21」虎

正解贪心考场只骗到了70分 做法一: 现将没有限制的边缩掉然后连边, 这样我们直接采用贪心的做法,因为每个边最多只会被反一次, 那么从叶子节点向上对于一个需要修改的边没直接令他向上直到不能修改 注意处理连在lca上有两条链的现象 1 #include<bits/stdc++.h> 2 #define MAXN 2100000 3 using namespace std; 4 struct node{int to;int n;}e[MAXN]; 5 int tot,head[MAXN]; 6 i

「模拟8.21」山洞(矩阵优化DP)

暴力: 正解: 考虑循环矩阵,f[i][j]表示从i点到j点的方案数 我们发现n很小,我们预处理出n次的f[i][j] 然后在矩阵快速幂中,我们要从当前的f[i][j]*f[j][k]-->fir[i][j] 但是此时的循环为三层 我们考虑转移式子的意义在0-n次从i-j,在n+1到2×n转移至j 这样此时的j-k其实可以把他看作从0开始走j-k步本质上是一样的 然后还有一个特判,就不讲了 for(int j=0;j<n;++j) { ff[now][j]=(ff[now][j]+ff[las

模拟赛 T3 dfs序+树状数组+树链的并+点权/边权技巧

code: #include <vector> #include <cstdio> #include <set> #include <cstring> #include <string> #include <algorithm> #define N 200007 #define ll long long using namespace std; void setIO(string s) { string in=s+".in&

一道模拟赛题

一道模拟赛题 简要题意: 树,单点修改,求直径,求必须选\(x\)的最长链,卡空间. 分析: 我们先把必须选的那个丢掉,发现他实际上是单点修改\(inf\)然后查树的直径. 如果不卡空间的话我们可以用点分树来搞一搞,不过由于一次修改会影响到很多点不能用堆来维护只能用支持区间修改的线段树,这样空间就开不下了. 我们还有动态\(DP\). 对一条重链维护\(lx\)表示必须选上端点向下延伸的最长链,\(rx\)表示必须选下端点向上延伸的最长链,\(s\)表示点权和,\(mx\)表示这些点及他们轻儿子