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

    [HNOI2011]XOR和路径

    给出一个n个点无向联通图以及其m条正整数边权,每次可以从一个顶点等概率选择一条出边,进入下一个顶点,定义一条路径的长度为该路径的异或和,询问从节点1到n的路径长度的期望,(N≤100,M≤100000)

    异或和自然想到线性基这一有力工具,而样本空间无限,自然使用期望代无限状态的方法,再加之概率不固定,考虑倒推,而异或不满足加和,这对期望是致命的,于是考虑二进制拆分,对边权的第k为考虑,于是设(E(x))为从x到终点n的路径该位为1的概率,y为x的出边,(dis[x][y])为x,y连边的边权的第k为上的数字,于是我们会有

    [E(x)=sum_{dis[x][y]==1}(1-E(y))+sum_{dis[x][y]==0}E(y) ]

    于是我们可以的到一个异或方程组,利用高斯消元,解出其值,结果乘上(2^k),对于每一位这样处理,累加结果即可。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define il inline
    #define ri register
    #define db long double
    #define exact 0.00000001
    using namespace std;
    struct base{
        db base[101];
    }A[101],*B[101];
    struct point{
        point*next;int to,len;
    }*pt,*head[101];
    int out[101],n;db ans;
    il void link(int,int,int),
        read(int&),insert(base&),eam();
    template<class free>il free Abs(free);
    int main(){
        int m,i,j,k;
        read(n),read(m);
        while(m--){
            read(i),read(j),read(k);
            link(i,j,k),++out[j];
            if(i!=j)link(j,i,k),++out[i];
        }
        for(i=0;i<=31;++i){
            memset(A,0,sizeof(A)),memset(B,0,sizeof(B));
            for(j=1;j<n;++j){
                A[j].base[j]=out[j];
                for(pt=head[j];pt!=NULL;pt=pt->next)
                    if(pt->len>>i&1)++A[j].base[pt->to],++A[j].base[0];
                    else --A[j].base[pt->to];insert(A[j]);
            }A[n].base[n]=1,insert(A[n]);
            ans+=(1<<i)*B[1]->base[0];
        }printf("%.3Lf",ans);
        return 0;
    }
    template<class free>
    il free Abs(free x){
        return x<0?-x:x;
    }
    il void insert(base &x){
        ri int i,j;
        for(i=n;i;--i)
            if(Abs(x.base[i])>exact){
                if(B[i]==NULL){
                    for(j=0;j<=i;++j)
                        x.base[j]/=x.base[i];
                    return (void)(B[i]=&x);
                }
                for(j=0;j<=i;++j)
                    x.base[j]-=B[i]->base[j]*x.base[i];
            }
    }
    il void read(int &x){
        x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
        while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    }
    il void link(int x,int y,int z){
        pt=new point,pt->to=y,pt->len=z;
        pt->next=head[x],head[x]=pt;
    }
    
    
  • 相关阅读:
    linux创建用户和组
    ftp上来显示的时间和系统时间不一致
    在Linux下如何用Shell脚本读写XML?现有一个config.xml(转)
    关于业务主键和逻辑主键
    git push 提示
    浏览器默认样式
    css实现缩进无限嵌套
    使用设置报头x-Frame-Options限制iframe网页嵌套
    chrome控制台小技巧
    git版本库底层命令
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10869029.html
Copyright © 2011-2022 走看看