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

    题面在这里

    题意:给定一个无向图,从1号节点出发,每次等概率选择连接该节点的一条边走到另一个节点,到达n号节点时,将走过的路径上的所有边权异或起来,求这个异或和的期望

    sol

    一道期望大火题(表示看了zsy大佬ycb大佬的题解才过去的orz)

    递推期望,因为是异或和,按照正常方法会很难,于是考虑按位DP(套路吧),即对于边权在二进制下的每一位分别讨论
    设状态的时候需要注意
    如果设(f[x])表示从1号节点到达x号节点且异或和为1的概率
    那么在转移的时候,因为到达n号节点的时候就已经停止,所以f[n]不能转移;而我们又必须求出(f[n]),因此必须先对除n以外的所有点进行计算,再推到n,这样会很麻烦
    于是想到倒着推,设(f[x])表示从x号节点到达n号节点且异或和为1的概率,答案为(f[1]),虽然说也不能从(f[n])转移,但因为要求解的不是(f[n])所以就让求解变得可行了

    通过边进行转移:

    [f[u]=sum_{v}frac{f[v]}{d[u]}*[(u,v)==0]+sum_{v}frac{1-f[v]}{d[u]}*[(u,v)==1] ]

    意即该位权值为1的点通过0边和该位权值为0的点通过1边到达点u所得的该位权值都是1

    由于每个f[u]都和另外的f[v]产生依赖关系,故无法直接递推求解
    高斯消元大显身手啦!!!!!!

    代码

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define mp make_pair
    #define pb push_back
    #define RG register
    #define il inline
    using namespace std;
    const int mod=1e9+7;
    const int N=110;
    const double eps=1e-10;
    typedef unsigned long long ull;
    typedef vector<int>VI;
    typedef long long ll;
    typedef double dd;
    il ll read(){
    	RG ll data=0,w=1;RG char ch=getchar();
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
    	return data*w;
    }
    
    int n,m,head[N],nxt[N*N*2],to[N*N*2],val[N*N*2],d[N],cnt;
    il void add(int u,int v,int w){
    	to[++cnt]=v;d[v]++;
    	val[cnt]=w;
    	nxt[cnt]=head[u];
    	head[u]=cnt;
    }
    
    dd S[35][N][N],ans[35][N],sum;
    il bool gauss(int a){
    	//高斯消元部分
    	for(RG int i=1;i<=n;i++){
    		for(RG int j=i;j<=n;j++)
    			if(abs(S[a][j][i])>eps){
    				swap(S[a][j],S[a][i]);break;
    			}
    		if(abs(S[a][i][i])<=eps)return 0;
    		for(RG int j=i+1;j<=n;j++){
    			ans[a][j]-=ans[a][i]*S[a][j][i]/S[a][i][i];
    			for(RG int k=n;k>=i;k--)
    				S[a][j][k]-=S[a][i][k]*S[a][j][i]/S[a][i][i];
    		}
    	}
    
    	for(RG int i=n;i;i--){
    		for(RG int j=i+1;j<=n;j++)
    			ans[a][i]-=S[a][i][j]*ans[a][j];
    		ans[a][i]/=S[a][i][i];
    	}
    	
    	return 1;
    }
    
    int main()
    {
    	n=read();m=read();
    	for(RG int i=1,u,v,w,t;i<=m;i++){
    		u=read();v=read();w=read();t=0;
    		add(u,v,w);if(u!=v)add(v,u,w);
    	}
    
        //这里是统计系数
    	for(RG int u=1;u<n;u++){
    		for(RG int i=0;i<=32;i++)S[i][u][u]+=1.0;
    		for(RG int i=head[u];i;i=nxt[i]){
    			RG int v=to[i],t=0;
    			while(t<=32){
    				S[t][u][v]+=((val[i]&1)?1:(-1))*1.0/(d[u]*1.0);
    				ans[t][u]+=((val[i]&1)?1:0)*1.0/(d[u]*1.0);
    				val[i]>>=1;t++;
    			}
    		}
    	}for(RG int i=0;i<=32;i++)S[i][n][n]+=1.0;
    	//这样可以保证最后f[n]==0消除f[n]的影响
    	
    	for(RG int i=0;i<=32;i++)gauss(i);
    	
    	for(RG ll i=0,x=1;i<=32;i++){sum+=ans[i][1]*x;x<<=1;}
    	//按位统计答案
    	
    	printf("%.3lf
    ",sum);
    	return 0;
    }
    

    注:还有一道[HNOI2013]游走和此题思想类似,题解在这里

  • 相关阅读:
    Hudson安装配置、部署应用及分析
    利用JMeter的beanshell进行接口的加密处理
    安装loadrunner时出现”命令行选项语法错误键入命令 ?获得帮助“的解决方法
    Oracle创建表空间、创建用户以及授权
    Linux 命令行模式 你需要知道的那些事
    Form onsubmit 事件 阻止表单提交() 必须选中同意选项才可以提交
    Django中Form的Textarea字段
    css实现自适应屏幕高度;
    Django 1.10 找不到静态资源解决方法
    时间戳 JavaScript parse() 方法 处理技巧
  • 原文地址:https://www.cnblogs.com/cjfdf/p/8401507.html
Copyright © 2011-2022 走看看