zoukankan      html  css  js  c++  java
  • BZOJ2337 XOR和路径

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

    题目

    有个无向图,从1走到N可以得到边权的序列,将这些权异或起来,可以得到一个值。现在你从1开始,每次等概率随机地选择一条边走向下一个点,一直走到N。问在N得到的异或的值的期望是多少。

    边权<=$10^9$

    N<=100,M<=10000,可能有重边和自环。

    题解

    xor就只能处理每一位了,如果边权上这一位是1,说明是1的概率会反过来变成是0的概率,因此概率变为(1-x)

    设dp[i][k]为从i出发到N时,第K位是1的概率

    因为期望有线性性,所以可以拆成31位计算。

    方程是

    [dp[i][k]=frac{1}{n}sum dp[j][k]]

    [dp[n][k]=0]

    n表示i点上面的边数,如果是自环,边数只能+1

    由于题目提示了精度,为了减小精度误差,应该尽量少用除法

    AC代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define REP(i,a,b) for(register int i=(a); i<(b); i++)
    #define REPE(i,a,b) for(register int i=(a); i<=(b); i++)
    #define PERE(i,a,b) for(register int i=(a); i>=(b); i--)
    using namespace std;
    typedef long long ll;
    int hd[107], nxt[20007], to[20007], vv[20007], deg[107], en;
    double dp[107][31];
    double arr[107][107][31];
    inline void adde(int a, int b, int v) {
    	nxt[en]=hd[a]; hd[a]=en; to[en]=b; vv[en]=v; en++;
    }
    int n,m;
    inline void calc() {
    	REP(k,0,31) {
    		REPE(i,1,n) {
    			int ch=i;
    			double ma=fabs(arr[i][i][k]);
    			REPE(j,i+1,n) {
    				if(fabs(arr[j][i][k])>ma) ch=j, ma=fabs(arr[j][i][k]);
    			}
    			if(ch!=i) REPE(j,0,n) swap(arr[i][j][k], arr[ch][j][k]);
    			REPE(j,i+1,n) {
    				double ra=arr[j][i][k]/arr[i][i][k];
    				REPE(x,i+1,n) arr[j][x][k]-=arr[i][x][k]*ra;
    				arr[j][0][k]-=arr[i][0][k]*ra;
    			}
    		}
    		PERE(i,n,1) {
    			REPE(j,i+1,n) arr[i][0][k]-=arr[i][j][k]*arr[j][0][k];
    			arr[i][0][k]/=arr[i][i][k];
    		}
    	}
    }
    int main() {
    	memset(hd,-1,sizeof hd);
    	scanf("%d%d", &n, &m);
    	en=0;
    	memset(deg,0,sizeof deg);
    	REP(i,0,m) {
    		int u,v,w; scanf("%d%d%d", &u, &v, &w);
    		if(u!=v) adde(u,v,w), deg[v]++;
    		adde(v,u,w);
    		deg[u]++;
    	}
    	memset(dp[n],0,sizeof(dp[n]));
    	memset(arr,0,sizeof arr);
    	REPE(i,1,n) REP(k,0,31) arr[i][i][k]=-1;
    	REP(i,1,n) {
    		double d=1.0/deg[i];
    		for(int p=hd[i]; ~p; p=nxt[p]) {
    			int j=to[p];
    			REP(k,0,31) {
    				int f=1<<k;
    				if(vv[p]&f) {
    					arr[i][j][k]-=d;
    					arr[i][0][k]-=d;
    				} else {
    					arr[i][j][k]+=d;
    				}
    			}
    		}
    	}
    	calc();
    	double ans=0;
    	REP(k,0,31) {
    		ans+=(1<<k)*arr[1][0][k];
    	}
    	printf("%.3f
    ", ans);
    }
    
  • 相关阅读:
    [题解?]luogu_P1415拆分数列(dp(不懂
    [题解]luogu_P1070道路游戏(堆dp
    [题解]luogu_P2577午餐(贪心dp
    [题解]luogu_P2157学校食堂(状压dp
    [模板]线段树合并
    [题解]宝藏(状压
    [题解]NOI2010超级钢琴
    [题解]luogu_P2161_会场预约(线段树颜色相关
    【总结】LCA的4种求法
    SRM517-600加强版(DP)
  • 原文地址:https://www.cnblogs.com/sahdsg/p/12505937.html
Copyright © 2011-2022 走看看