记录编号 160437 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [ZJOI 2015]地震后的幻想乡 最终得分 100
用户昵称 GravatarAsm.Def 是否通过 通过
代码语言 C++ 运行时间 0.057 s
提交时间 2015-04-27 09:23:20 内存使用 0.32 MiB
显示代码纯文本
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cctype>
#include <algorithm>
#include <cmath>
using namespace std;
//#define USEFREAD
#ifdef USEFREAD
#define InputLen 5000000
char *ptr=(char *)malloc(InputLen);
#define getc() (*(ptr++))
#else
#define getc() (getchar())
#endif
#define SetFile(x) (freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout))
template<class T>inline void getd(T &x){
	int ch = getc();bool neg = false;
	while(!isdigit(ch) && ch != '-')ch = getc();
	if(ch == '-')ch = getc(), neg = true;
	x = ch - '0';
	while(isdigit(ch = getc()))
		x = x * 10 - '0' + ch;
	if(neg)x = -x;
}
/***********************************************************************/
#ifdef DEBUG
#define __float128 double//因为蒟蒻的编译器太老了不支持__float128...
#endif
typedef long long LL;
#include <vector>
typedef vector<LL> Poly;

inline void operator += (Poly &a, const Poly &b){//要求a != b
	Poly ans(max(a.size(), b.size()), 0);
	for(unsigned i = 0;i < ans.size();++i){
		if(i < a.size())ans[i] += a[i];
		if(i < b.size())ans[i] += b[i];
	}
	a = ans;
}

inline Poly operator * (const Poly &a, const Poly &b){
	Poly ans(a.size() + b.size() - 1, 0);
	unsigned i, j;LL k;
	for(i = 0;i < a.size();++i){
		k = a[i];
		for(j = 0;j < b.size();++j)ans[i + j] += k * b[j];
	}
	return ans;
}

inline Poly operator - (const Poly &a, const Poly &b){
	Poly Ans(max(a.size(), b.size()), 0);
	unsigned i, end = min(Ans.size(), b.size());
	for(i = 0;i < a.size();++i)Ans[i] = a[i];
	for(i = 0;i < end;++i)Ans[i] -= b[i];
	return Ans;
}

Poly op(2), True(1, 1), F[1025], Pow[26];

int N, M, adj[11], USet;
inline void init(){
	int i, u, v;
	getd(N), getd(M);
	USet = (1 << N) - 1;
	while(M--){
		getd(u), getd(v);
		--u, --v;
		adj[u] |= (1 << v);
		adj[v] |= (1 << u);
	}
	op[0] = 1, op[1] = -1;
	Pow[0] = True;
	for(i = 1;i <= 25;++i)Pow[i] = Pow[i-1] * op;
}

inline void Calc(){
	__float128 Ans = 0;
	unsigned i, end = F[USet].size();
	for(i = 0;i < end;++i)Ans += (__float128)F[USet][i] / (i + 1);
	printf("%.6lf\n", 1.0 - (double)Ans);
}

#include <queue>
bool inc[1025] = {0, 1};//是否是包含1的连通块

#ifdef DEBUG
void Print(Poly x){
	for(int i = x.size()-1;i >= 0;--i)printf("%d ", x[i]);
	putchar('\n');
}
#endif

inline void work(){
	int t, i, j, b, e, cnt, it;
	queue<int> Q;Q.push(1);
	while(!Q.empty()){
		t = Q.front();Q.pop();
		for(j = 0, b = 1;j < N;++j, b <<= 1)if(t & b){
			e = adj[j];
			while(e){
				e ^= (i = e & -e);
				if(t & i || inc[t ^ i])continue;
				inc[t ^ i] = true;
				Q.push(t ^ i);
			}
		}
	}
	F[1] = True;
	for(i = 2;i <= USet;++i)if(inc[i]){
		for(j = (i - 1) & i;j;(--j) &= i)if(inc[j]){
			cnt = 0;
			for(t = 0, b = 1;t < N;++t, b <<= 1)if(j & b){
				e = adj[t];
				while(e){
					e ^= (it = e & -e);
					if((i ^ j) & it)++cnt;
				}
			}
			F[i] += F[j] * Pow[cnt];
		}
		F[i] = True - F[i];
	}
	/*#ifdef DEBUG
	for(i = 1;i <= USet;++i)if(inc[i]){
		printf("%d: ", i);
		Print(F[i]);
	}
	#endif*/
	Calc();
}

int main(){
	#ifdef DEBUG
	freopen("test.txt", "r", stdin);
	#else       
	SetFile(zjoi15_mst);
	#endif
	#ifdef USEFREAD
	fread(ptr,1,InputLen,stdin);
	#endif
	
	init();
	
	work();
	
#ifdef DEBUG
    printf("\n%.3lf sec \n", (double)clock() / CLOCKS_PER_SEC);
#endif
    return 0;
}