Live2D

Solution -「ZJOI 2015」「洛谷 P3343」地震后的幻想乡

Description

  Link.

  给定连通图简单无向 G=(V,E),对于 eE,有边权 te 独立均匀随机生成自 [0,1]。求 G 的生成树最大边权最小值的期望,不取模。

  n10

Solution

(1)E(minTmaxeETte)=01P[minTmaxeETte>x] dx(2)=01P[T,eET,te>x] dx(3)=01P[G is not connected by e whose te<x] dx(4)=01E1E2=E,E1E2=[G is not connected by E1]x|E1|(1x)|E2| dx(5)=E1E2=E,E1E2=[G is ...]01x|E1|(1x)|E2| dx(6)=E1E2=E,E1E2=[G is ...]i=0|E2|(1)i(|E2|i)01x|E1|+i dx(7)=E1E2=E,E1E2=[G is ...]i=0|E2|(1)i(|E2|i)1|E1|+i+1(8)=u0SVi=0inc(S)g(S,i)jt=i+cut(S,VS)(inc(VS)jt)f(j).

  以上是草稿,来解释一下。

  从 (1)(7),其实就干了一件事——把积分丢到简单函数上消掉。毕竟我也只会求简单函数的积分。(8) 的目的是把边的枚举更多的变为点的枚举。其中,f(|E2|) 即对 (7) 中第二层和式的换元,这个可以直接求。第一个和式的 u0SV 是常见子集 DP trick,即枚举 E1G 下形成的包含某个特定结点的连通块,g(S,i) 表示在 S 的诱导子图内删掉恰 i 条边,使得子图连通的方案数。子集 DP 一下可以 O(3nnm)(上界很粗)求出来。那么本题就结束了。

  提示:2022 年了,选手可以使用 __int128__float128

Code

/*+Rainybunny+*/

#include <bits/stdc++.h>

#define rep(i, l, r) for (int i = l, rep##i = r; i <= rep##i; ++i)
#define per(i, r, l) for (int i = r, per##i = l; i >= per##i; --i)

typedef __int128 LL;
typedef __float128 LD;

const int MAXN = 10, MAXM = 45;
int n, m, adj[MAXN + 5], inc[1 << MAXN];
LD f[MAXM + 5];
LL bino[MAXM + 5][MAXM + 5], g[1 << MAXN][MAXM + 5];

inline void init() {
    bino[0][0] = 1;
    rep (i, 1, m) {
        bino[i][0] = 1;
        rep (j, 1, i) bino[i][j] = bino[i - 1][j - 1] + bino[i - 1][j];
    }
    rep (i, 0, m) {
        rep (j, 0, i) {
            f[i] += (j & 1 ? -1. : 1.) * LD(bino[i][j]) / (m - i + j + 1.);
        }
    }
    rep (S, 1, (1 << n) - 1) {
        inc[S] = inc[S ^ (S & -S)]
          + __builtin_popcount(adj[31 - __builtin_clz(S & -S)] & S);
    }
}

int main() {
    scanf("%d %d", &n, &m);
    rep (i, 0, m - 1) {
        int u, v; scanf("%d %d", &u, &v);
        adj[u - 1] |= 1 << v >> 1, adj[v - 1] |= 1 << u >> 1;
    }

    init();
    LD ans = 0.;
    rep (S, 0, (1 << n) - 2) if (S & 1) {
        rep (i, 0, inc[S]) g[S][i] = bino[inc[S]][i];
        for (int T = (S - 1) & S; T; T = (T - 1) & S) if (T & 1) {
            int cut = inc[S] - inc[T] - inc[S ^ T];
            rep (i, cut, inc[S]) {
                rep (j, 0, std::min(i - cut, inc[T])) {
                    g[S][i] -= g[T][j] * bino[inc[S ^ T]][i - j - cut];
                }
            }
        }

        int incT = inc[((1 << n) - 1) ^ S], cut = m - inc[S] - incT;
        rep (i, 0, inc[S]) {
            LD tmp = 0.;
            rep (j, i + cut, m - inc[S] + i) {
                tmp += bino[incT][j - i - cut] * f[j];
            }
            ans += g[S][i] * tmp;
        }
    }
    printf("%Lf\n", (long double)ans);
    return 0;
}

posted @   Rainybunny  阅读(44)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示