zoukankan      html  css  js  c++  java
  • bzoj千题计划191:bzoj2337: [HNOI2011]XOR和路径

    http://www.lydsy.com/JudgeOnline/problem.php?id=2337

    概率不能异或

    但根据期望的线性,可以计算出每一位为1的概率,再累积他们的期望

    枚举每一位i,现在要计算从1出发第i位异或和为1的概率

    令f[u]表示从点u出发,第i为为1的概率

    d[u]表示u的度数

    枚举与u相连的v

    若边权的第i位为1,那么v的第i位为0,f[u]+=(1-f[v])/d[u]

    若边权的第i位为0,那么v的第i位为1,f[u]+=f[v]/d[u]

    还有一个f[n]=0

    将这n个式子,f[i]看做未知数,1/d[i]看做系数

    把f[i]都移到左边,1/d 都移到右边

    得到n个方程,高斯消元解出来

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define N 101
    #define M 10001
    
    const double eps=1e-7;
    
    int n;
    
    int d[N];
    int to[M<<1],nxt[M<<1],front[N],val[M<<1],tot;
    
    double a[N][N];
    
    int bit[31];
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void add(int u,int v,int w)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w;
    }
    
    void gauss()
    {
        int r;
        double f;
        for(int i=0;i<n;++i)
        {
            r=i;
            for(int j=i+1;j<n;++j)
                if(abs(a[j][i])>abs(a[r][i])) r=j;
            if(r!=i) swap(a[r],a[i]);
            for(int k=i+1;k<n;++k)
            {
                f=a[k][i]/a[i][i];
                for(int j=i;j<=n;++j) a[k][j]-=f*a[i][j];
            }
        }
        for(int i=n-1;i>=0;--i)
        {
            for(int j=i+1;j<n;++j) a[i][n]-=a[j][n]*a[i][j];
            a[i][n]/=a[i][i];
        }    
    }
    
    int main()
    {
        int m;
        read(n); read(m);
        int x,y,w;
        while(m--)
        {
            read(x); read(y); read(w);
            add(x,y,w),d[y]++;
            if(x!=y) add(y,x,w),d[x]++;
        }
        bit[0]=1;
        for(int i=1;i<30;++i) bit[i]=bit[i-1]<<1;
        double ans=0;
        for(int i=0;i<30;++i)
        {
            memset(a,0,sizeof(a));
            for(int j=1;j<n;++j)
            {
                a[j-1][j-1]=1;
                for(int k=front[j];k;k=nxt[k])
                    if(val[k]&bit[i]) 
                    {
                        a[j-1][to[k]-1]+=1.0/d[j];
                        a[j-1][n]+=1.0/d[j];
                    }
                    else a[j-1][to[k]-1]-=1.0/d[j];
            }
            a[n-1][n-1]=1;
            gauss();
            ans+=a[0][n]*bit[i];
        }
        printf("%.3lf",ans);
    }
  • 相关阅读:
    Hql语句注意事项总结
    数据库主键设计之思考
    UTF8的中文问题
    DirectShow SDK笔记【关于DirectShow(4)】
    关于kindeditor上传图片出现"服务器发生故障"的解决办法
    php 分隔字符串为数组
    yum 一次性安装 apache mysql php
    linux下安装gd库
    三种实现PHP伪静态页面的方法
    (转)Linux利器 strace
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8192404.html
Copyright © 2011-2022 走看看