首页 > 其他分享 >ZJOI2015 地震后的幻想乡

ZJOI2015 地震后的幻想乡

时间:2023-10-20 18:46:59浏览次数:43  
标签:幻想 联通 limits sum 枚举 子集 地震 ZJOI2015 我们

「ZJOI2015」地震后的幻想乡


前言:

想了很久,最后只能失败告终。

基本分析到了一半,只是没有将其转化为古典概型后考虑求解方案数。

说实话有点可惜……


题意:

给定一张 \(n\) 个点 \(m\) 条边的无向连通图,每条边的边权是 \([0,1]\) 之间的随机实数,求其最小生成树上最大边权的期望值。

数据范围:\(n \le 10\),无重边与自环。

提示:对于 \(n\) 个 \([0,1]\) 之间的随机变量 \(x_1,x_2,\cdots,x_n\),第 \(k\) 小的那个的期望值是 \(\frac{k}{n+1}\)。


思路:

首先根据题目提示我们可以猜到我们需要求解最后的最小生成树上最大边的排名的期望值。

(P.S 这里的排名指的是 \(m\) 条边的边权大小排名。)

这个值不好求,我们想到期望的定义是加权平均。

我们可以枚举最大边排名为 \(i\) 的情况,然后将其加权平均。

也就是 \(ans = \sum\limits_{i=1}^{m} E(i)P(L = i)\),其中 \(P(L = i)\) 表示最大边排名为 \(i\) 的概率,\(E(i)\) 表示的是当排名为 \(i\) 时的期望值。

然后求解最大边排名为 \(i\) 的概率,实质上我们要考虑的是将前 \(i\) 小的边全部加入后,图恰好联通的概率。

这个时候发现我们将实数的取值变成了排名。

此时的题目是一个古典概型,能够通过求解方案数得到概率。

因此我们继续考虑方案数怎么求。

此时我们对于一个点集进行思考,考虑这一个点集一共使用了 \(x\) 条边联通起来的情况。

我们设 \(F(S,x)\) 表示点集 \(S\) 用了 \(x\) 条边使得 \(S\) 联通的方案数。

一个点集要么联通要么不联通……

那么设 \(G(S,x)\) 表示不联通的方案数,则 \(F(S,x) + G(S,x) = \dbinom{cnt_S}{x}\),其中 \(cnt_S\) 表示点集 \(S\) 中有多少条边。

接下来我们就需要考虑怎么使用 \(F\) 和 \(G\) 表示出我们所需的答案。

考虑到 \(ans = \sum\limits_{i=1}^{m} E(i)P(L = i)\)。

根据题目的提示,我们可以简单地把上面的式子转化一下:

\[ans = \sum\limits_{i=1}^{m} \dfrac{i \times P(L = i)}{m + 1} \]

这是很显然的,我们设 \(H = \sum\limits_{i=1}^{m} i \times P(L = i)\):

那么很容易发现 \(H = \sum\limits_{i=1}^{m} P(L \ge i)\)。

这个时候我们就要让前 \(i\) 小的边无法联通,也就达成了最大边在 \(i\) 及其之后的目的。

也就是 \(H=\sum\limits_{i=1}^{m} \dfrac{G(S,i - 1)}{tot}\),其中 \(tot\) 是总方案数。

于是题目很明了了,我们需要求解 \(G\)。


实现:

考虑 \(G\) 如何求解。

这里我们考虑 \(S\) 的子集,\(S\) 必定会从子集 \(T\) 转移而来。

为了要使得 \(S\) 不联通,很容易想到使得 \(T\) 和 \(S - T\) 不联通。

那么我们只需要让所有选择的边都在 \(S - T\) 内不就行了?

这样一定不联通,状态转移方程就能够写出来:

\[G_{S,x} = \sum\limits_{T \in S,0 \le x \le m,0 \le y \le x} F_{T,y}\times \dbinom{cnt_{S-T}}{x-y} \]

然后根据 \(F(S,x) + G(S,x) = \dbinom{cnt_S}{x}\) 计算 \(F(S,x)\) 即可。


细节:

  • 1.子集枚举

这个知识点不难,但是我觉得有必要拉出来讲讲。

状态压缩的时候,对于一个状态 \(S\),我们有时需要去枚举它的子集,如果暴力枚举会直接让时间复杂度乘上一个平方,这显然是不行的。

那么我们怎么优化?

考虑如何不重不漏地遍历当前状态的所有子集。

想到 \(S\) 的子集所对应的二进制数是一定小于 \(S\) 的,那么我们就可以通过将 \(S\) 递减来枚举子集。

在递减的时候,有时当前递减到的状态中出现了一些 \(S\) 中不存在的 1

这些 1 其实可以直接去掉,因为递减的过程中会不断去掉这些 1,直接将其去掉依旧能够保证不重不漏。

因此我们就写出了直接枚举所有子集的代码:

for (int S = 1; S <= tot; S++) {
    for (int T = (S - 1)&S; T; T = (T - 1)&S) {
    	//写点什么...
    }
}
  • 2.DP转移

这里我们涉及到的DP比较特殊,因为我们在计算的是不连通方案。

按照我们的思路想来看上去没有问题,但实际上计算的时候会发现算重了。

因为什么?在我们计算的时候会发现可能有一些方案选择的边是相同的,但是对应的 \(T\) 不一样。

这时我们简单模拟一下会发现对应的这些 \(T\) 中不存在公共点并且将 \(S\) 完全覆盖,因此我们提前在 \(S\) 中指定一个点 \(p\),强制要求 \(T\) 中包含 \(p\) 即可做到不重不漏的计数。


代码(由LOJ格式化):

#include <bits/stdc++.h>
using namespace std;
const int N = 15;
#define ll long long
ll F[1 << N][N * N], G[1 << N][N * N], C[N * N][N * N];
int cnt[1 << N];
bool e[N][N];
int main() {
    int n, m;
    scanf("%d%d", &n, &m);

    for (int i = 1; i <= m; i++) {
        int a, b;
        scanf("%d%d", &a, &b);
        a--, b--;
        e[a][b] = e[b][a] = true;
    }

    int tot = (1 << n) - 1;

    //预处理 cnt
    for (int i = 1; i <= tot; i++) {
        for (int j = 0; j < n; j++)
            if ((i >> j) & 1)
                for (int k = j + 1; k < n; k++)
                    if (((i >> k) & 1) && e[j][k])
                        cnt[i]++;
    }

    //预处理组合数
    C[0][0] = 1;

    for (int i = 1; i <= m; i++)
        for (int j = 0; j <= i; j++)
            if (j == 0)
                C[i][j] = 1;
            else
                C[i][j] = C[i - 1][j - 1] + C[i - 1][j];

    //DP!
    for (int S = 1; S <= tot; S++) {
        int sz = 0; //计算当前集合有多少个点
        int p = 0; //不重不漏

        for (int i = 0; i < n; i++)
            if ((S >> i) & 1)
                sz++, p = (1 << i);

        if (sz == 1) { //只有一个点,直接联通
            F[S][0] = 1;
            continue;
        }

        for (int T = (S - 1)&S; T; T = (T - 1)&S) {
            if (!(T & p))
                continue;    //这里有常数优化,因此看上去有所差别

            for (int x = 0; x <= cnt[S] + cnt[S - T]; x++)
                for (int y = 0; y <= cnt[T]; y++)
                    if (x - y <= cnt[S - T])
                        G[S][x] += F[T][y] * C[cnt[S - T]][x - y];
        }

        for (int i = 0; i <= m; i++)
            F[S][i] = C[cnt[S]][i] - G[S][i];
    }

    double ans = 0;

    for (int i = 0; i <= m; i++)
        ans += G[tot][i] / (double)C[cnt[tot]][i]; //总方案数就是 C(cnt[tot],i)

    printf("%.6lf", ans / (double)(m + 1));
    return 0;
}

上面的代码的时间复杂度为 \(O(3^n m^2)\),其中子集枚举的时间复杂度是 \(O(3^n)\),可由二项式定理简单证得。

根据评测结果来看,效率比较优秀。

标签:幻想,联通,limits,sum,枚举,子集,地震,ZJOI2015,我们
From: https://www.cnblogs.com/XiaoShanYunPan/p/17777781.html

相关文章

  • hdu:悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
    ProblemDescription急!灾区的食物依然短缺!为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买。请问:你用有限的资金最多能采购多少公斤粮食呢?后记:人生是一个充满了......
  • 「题解注释」P3345 [ZJOI2015] 幻想乡战略游戏
    题解P3345【[ZJOI2015]幻想乡战略游戏】-Baka'sBlog-洛谷博客(luogu.org)耗时:半个下午代码注释:#include<bits/stdc++.h>typedeflonglongLL;inlineintrd(){ inta=1,b=0;charc=getchar(); while(!isdigit(c))a=c=='-'?0:1,c=getcha......
  • 可以救命的地震预警你开了吗?
    如何在手机上开启地震预警功能呢?山东地震,很多人都不知道还有地震预警这回事,很多人都发微博说幸好被手机的地震预警叫醒了,但是手机预警是需要自己设置的。在中国,手机地震预警功能是由中国地震局和三大运营商合作开发的。用户只需在手机设置中开启地震预警功能即可。以下是在不同......
  • 可以救命的地震预警你开了吗?
    如何在手机上开启地震预警功能呢?山东地震,很多人都不知道还有地震预警这回事,很多人都发微博说幸好被手机的地震预警叫醒了,但是手机预警是需要自己设置的。在中国,手机地震预警功能是由中国地震局和三大运营商合作开发的。用户只需在手机设置中开启地震预警功能即可。以下是在不同......
  • 传奇引擎知识分享HxM2幻想引擎简单介绍与假人功能设置
    HxM2幻想游戏开发引擎又被传奇GM们称为HX引擎,也叫幻想引擎,相对于现在流行的传奇版本中,幻想HX是一个低产的引擎,现在已经非常小众化了,可能由于年代久远,款引擎现在使用的很少,但是也出过非常火爆的版本,比如灵域迷失系列、恶魔大极品等等……HXM幻想引擎也现在仍在更新,而且一直有保持免......
  • 2023-7-10 #65 我守着虚构的幻想 那些我珍视的模样
    448QOJ6669Mapa这谁想得到啊??????????????????插出一个模1e9+7下的多项式,保存系数。449CF1456EXOR-ranges感觉挺难的。类似406HDU6358Innocence,我们将每一段拆成\(\log\)个trie上的区间,每一个形如“固定前缀\(S\),长为\(l\)的后缀任选”,并将选择\([l,r]\)内的数改为在这\(\l......
  • 柏林噪声&幻想大陆地图生成
    序言之前介绍过perlin噪声的实现,现在应用实践一下——程序化生成幻想大陆这里使用的是perlin噪声倍频技术(也称分形噪声),详情传送门:柏林噪声算法代码示例使用的是shadertoy的语法规则,shandertoy传送门:ShaderToy示例#defineamp1.9#definefre1.#defineoct5.#definela......
  • luogu P3345 [ZJOI2015]幻想乡战略游戏
    P3345[ZJOI2015]幻想乡战略游戏这道题还是比较有意思的,做了一个比较长的时间,但是点分树实在是太毒瘤了,所以记录一下线段树的做法。题面给一棵树,有边权,每次修改一个点的点权,修改完后输出所有点到这棵树的带权重心的贡献,即\(\sumdis_i\timesval_i\)题解考虑朴素的暴......
  • (转)巧妙去除幻想游戏植入的广告
    巧妙去除幻想游戏植入的广告    一提起休闲小游戏,恐怕大家都玩过,对于上班一族以及工作紧张的人来说,在家玩玩休闲类小游戏是个不错的选择。目前,在休闲小游戏网站中最著名的莫过于幻想游戏了(对于国内来说)。然而玩家最痛恨也是最反感的就是幻想游戏中带的广告,不仅在打开游戏以及......
  • 「ZJOI2015」地震后的幻想乡
    「ZJOI2015」地震后的幻想乡题意:给定一张图,每条边的边权在\([0,1]\)中随机,求最小生成树的最大边权的期望。其中这个很重要:对于\(n\)个\([0,1]\)之间的随机变量,第\(k\)小的那个的期望值是\(\frac{k}{n+1}\)那暴力就很容易了,假设我们已经按边权从小到大排好了序,也就是相......