zoukankan      html  css  js  c++  java
  • bzoj2337 [HNOI2011]XOR和路径

    题目链接

    solution

    首先想对于每个二进制位分别计算。

    (f[i])表示第(i)个点走到(n)异或和为(1)的概率。用(du[i])表示第(i)个点的度数,那么就有

    [f[u]=frac{1}{du[u]}(sumlimits_{w(u,v)=1}(1-f[v])+sumlimits_{w(u,v)=0}f[v])\ Rightarrow du[u]f[u]=sumlimits_{w(u,v)=1}1-sumlimits_{w(u,v)=1}f[v]+sumlimits_{w(u,v)=0}f[v]\ Rightarrow sumlimits_{w(u,v)=1}1=du[u]f[u]+sumlimits_{w(u,v)=1}f[v]-sumlimits_{w(u,v)=0}f[v] ]

    然后高斯消元就行了。

    对于第(x)位的答案就是(2^x imes a[1][1])

    code

    /*
    * @Author: wxyww
    * @Date:   2020-04-27 18:46:32
    * @Last Modified time: 2020-04-27 19:31:34
    */
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    const int N = 110;
    ll read() {
    	ll x = 0,f = 1;char c = getchar();
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1; c = getchar();
    	}
    	while(c >= '0' && c <= '9') {
    		x = x * 10 + c - '0'; c = getchar();
    	}
    	return x * f;
    }
    struct node {
    	int v,nxt,w;
    }e[N * N * 2];
    int du[N],head[N],ejs;
    void add(int u,int v,int w) {
    	e[++ejs].v = v;e[ejs].nxt = head[u];head[u] = ejs;e[ejs].w = w;
    }
    int n,m;
    double a[N][N];
    void pre(int x) {
    	x = (1 << x);
    	a[n][n] = 1;//f[n] = 1!!!
    	memset(a,0,sizeof(a));
    	for(int u = 1;u < n;++u) {//u < n !!!!
    		a[u][u] = du[u];
    		for(int i = head[u];i;i = e[i].nxt) {
    			int v = e[i].v;
    			if(e[i].w & x) a[u][v]++,a[u][n + 1]++;
    			else a[u][v]--;
    		}
    	}
    }
    void Guass() {
    	for(int i = 1;i <= n;++i) {
    		int t = i;
    		for(int j = i + 1;j <= n;++j)
    			if(a[j][i] > a[t][i]) t = j;
    
    		if(fabs(a[t][i]) < 1e-8) continue;
    
    		swap(a[i],a[t]);
    
    		for(int j = 1;j <= n;++j) {
    			if(j == i) continue;
    			double tmp = a[j][i] / a[i][i];
    			for(int k = 1;k <= n + 1;++k) 
    				a[j][k] -= a[i][k] * tmp;
    		}
    
    	}
    }
    int main() {
    	n = read(),m = read();
    	for(int i = 1;i <= m;++i) {
    		int u = read(),v = read(),w = read();
    		add(u,v,w);
    		du[u]++;
    		if(u != v) 
    			du[v]++,add(v,u,w);
    	}
    	double ans = 0;
    	for(int i = 30;i >= 0;--i) {
    		pre(i);
    		Guass();
    
    		ans += (a[1][n + 1] / a[1][1]) * (1 << i);
    	}
    	printf("%.3lf
    ",ans);
    
    	return 0;
    }
    
    /*
    3 3
    1 2 4
    1 3 5
    */
    
  • 相关阅读:
    一部感天动地的自学编码之旅
    c++初学
    imooc-c++学习感悟
    第二次实践作业
    大一下学期的自我目标(要求包含对大一上学期的总结、对面向对象课程完成后学习到的能力的预期,对面向对象课程的期望、对编程和专业能力的愿景规划)
    面向对象程序设计 ——第二次作业(2)
    面向对象程序设计 ——第二次作业(1)
    面向对象程序设计 ——第一次作业
    面对对象程序设计第二次作业2
    面对对象程序设计第二次作业
  • 原文地址:https://www.cnblogs.com/wxyww/p/bzoj2337.html
Copyright © 2011-2022 走看看