zoukankan      html  css  js  c++  java
  • 【洛谷3343_BZOJ3925】[ZJOI2015]地震后的幻想乡(状压 DP_期望)

    题目:

    洛谷 3343

    BZOJ 3925

    分析:

    谁给我说这是个期望概率神题的,明明没太大关系好吧

    「提示」里那个结论哪天想起来再问 Jumpmelon 怎么证。

    首先,由于开始修路前 (e_i) 就已知了,所以显然是按照 (e_i) 从小到大的顺序修,直到连通。代价就是最后加入的边的权值。

    这个提示非常地良心,同时结合期望的线性性可以发现答案就是对于所有的 (k(0leq kleq m)) ,任选 (k) 条边 恰好 连通 (n) 个点的概率乘上第 (k) 大的边权值的期望(即提示中的 (frac{k}{m+1}) )。(注意,这里不需要考虑边的顺序。因为相当于每加入一条边都看一眼有没有连通,连通就退出,否则继续。所以当前是否退出只与之前选了哪些边有关,而与具体的顺序无关。)任意选 (k) 条边的方案数是 (C_m^k) ,恰好联通的概率就是恰好连通的方案数除以 (C_m^k) ,我们现在只需要求出恰好联通的方案数即可。于是现在变成了一个 在 CTS2019 中喜闻乐见的 计数题,和期望概率那一套已经没有任何关系了。

    (n) 很小,考虑状压 DP 。设 (f_{S,i}) 表示选了 (i) 条边使 (S) 集合中的点 恰好 连通的方案数。这个「恰好」不好做, 正难则反 (这步真没想到),设 (g_{S,i}) 表示选了 (i) 条边还没有连通的方案数,则 (f_{S,i}=g_{S,i-1}-g_{S,i}) 。对于 (g_{S,i}) 的转移,为了不重不漏地计数,大力枚举某个 特定的点 所在连通块的大小(类似于 【洛谷4841】城市规划(多项式) 的思路),然后这个连通块之外的边可以随便选。即:

    [g_{S,i}=sum_{T}sum_{j=0}^i (C_{mathrm{num}_T}^j-g_{T,j})cdot C_{mathrm{num}_{S-T}}^{i-j} ]

    其中 ((C_{mathrm{num}_T}^j-g_{T,j})) 就是在 (T) 中选 (j) 条边使其连通(不一定恰好)的方案数,(T)(S) 的真子集且 (mathrm{lowbit}(T)=mathrm{lowbit}(S)) (把 (S) 中编号最小的点作为上述的「特定的点」),(S-T) 表示 (T) 相对于 (S) 的补集,(mathrm{num}_S) 表示两端均在 (S) 中的边的数量。

    暴力转移即可。时间复杂度 (O(3^nm))

    代码:

    组合数最大 (C_{45}^{22}approx 4 imes 10^{12}) ,所以直接 long long 就可以存下。

    小恐龙教的条件编译真好用

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cctype>
    using namespace std;
    
    namespace zyt
    {
    	template<typename T>
    	inline bool read(T &x)
    	{
    		char c;
    		bool f = false;
    		x = 0;
    		do
    			c = getchar();
    		while (c != EOF && c != '-' && !isdigit(c));
    		if (c == EOF)
    			return false;
    		if (c == '-')
    			f = true, c = getchar();
    		do
    			x = x * 10 + c - '0', c = getchar();
    		while (isdigit(c));
    		if (f)
    			x = -x;
    		return true;
    	}
    	template<typename T>
    	inline void write(T x)
    	{
    		static char buf[20];
    		char *pos = buf;
    		if (x < 0)
    			putchar('-'), x = -x;
    		do
    			*pos++ = x % 10 + '0';
    		while (x /= 10);
    		while (pos > buf)
    			putchar(*--pos);
    	}
    	inline void write(const double &x, const int fixed = 9)
    	{
    		printf("%.*f", fixed, x);
    	}
    	typedef long long ll;
    	const int N = 10, M = N * N / 2, S = (1 << N);
    	ll g[S][M], C[M][M];
    	int num[S], n, m;
    	struct ed
    	{
    		int u, v;
    	}e[M];
    	inline bool check(const int a, const int p)
    	{
    		return a & (1 << p);
    	}
    	inline int lowbit(const int x)
    	{
    		return x & (-x);
    	}
    	int work()
    	{
    		read(n), read(m);
    		for (int i = 0; i < m; i++)
    		{
    			read(e[i].u), read(e[i].v);
    			--e[i].u, --e[i].v;
    		}
    		for (int i = 0; i <= m; i++)
    		{
    			C[i][0] = 1;
    			for (int j = 1; j <= i; j++)
    				C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
    		}
    		for (int i = 0; i < (1 << n); i++)
    			for (int j = 0; j < m; j++)
    				if (check(i, e[j].u) && check(i, e[j].v))
    					++num[i];
    		for (int i = 0; i < n; i++)
    			g[1 << i][0] = 0;
    		for (int S = 1; S < (1 << n); S++)
    			for (int T = (S - 1) & S; T; T = (T - 1) & S)
    				if (lowbit(T) == lowbit(S))
    					for (int i = 0; i <= m; i++)
    						for (int j = 0; j <= i; j++)
    							g[S][i] += (C[num[T]][j] - g[T][j]) * C[num[S ^ T]][i - j];
    		double ans = 0;
    		for (int i = 1; i <= m; i++)
    			ans += double(i) / (m + 1) * 
    				(double(g[(1 << n) - 1][i - 1]) / C[m][i - 1] - double(g[(1 << n) - 1][i]) / C[m][i]);
    		write(ans, 6);
    		return 0;
    	}
    }
    int main()
    {
    #ifdef BlueSpirit
    	freopen("3343.in", "r", stdin);
    #endif
    	return zyt::work();
    }
    
  • 相关阅读:
    不相交集实现实例
    TQ2440开发板挂载U盘出现乱码
    快速选择实例
    linux2.6.30.4内核移植(7)——插入hello world驱动模块
    linux2.6.30.4内核移植(6)——移植应用程序hello world常见的错误:-bin/sh ./hello not found
    linux2.6.30.4内核移植(5)——构建根文件系统(yaffs文件系统格式的镜像)
    linux2.6.30.4内核移植(4)——完善串口驱动
    linux2.6.30.4内核移植(3)——yaffs文件系统移植
    linux2.6.30.4内核移植(2)——Nand Flash驱动移植
    快速排序实例
  • 原文地址:https://www.cnblogs.com/zyt1253679098/p/10913026.html
Copyright © 2011-2022 走看看