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);
}
原文地址:https://www.cnblogs.com/sahdsg/p/12505937.html