BZOJ 2337 XOR和路径(概率DP)
求点1到点n经过的路径权值异或和的期望。
考虑按位计算,对于每一位来说,令dp[i]表示从i到n的异或和期望值。
那么dp[i]=sum(dp[j]+1-dp[k]).如果w(i,j)这一位为0,如果w(i,k)这一位为1.边界为dp[n][n]=0.
那么求解每个方程组就得到了每一位的贡献。另外注意自环的出理就ok了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set> # include <cmath> # include <algorithm> using namespace std; # define lowbit(x) ((x)&(-x)) # define pi acos(-1.0) # define eps 1e-9 # define MOD 1000000000 # define INF 1000000000 # define mem(a,b) memset(a,b,sizeof(a)) # define FOR(i,a,n) for(int i=a; i<=n; ++i) # define FO(i,a,n) for(int i=a; i<n; ++i) # define bug puts("H"); # define lch p<<1,l,mid # define rch p<<1|1,mid+1,r # define mp make_pair # define pb push_back typedef pair<int,int> PII; typedef vector<int> VI; # pragma comment(linker, "/STACK:1024000000,1024000000") typedef long long LL; int Scan() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void Out(int a) { if(a<0) {putchar('-'); a=-a;} if(a>=10) Out(a/10); putchar(a%10+'0'); } const int N=105; //Code begin... struct Edge{int p, next, w;}edge[20005]; int head[N], cnt=1, dee[N]; double a[N][N], x[N]; int equ, var; void add_edge(int u, int v, int w){ edge[cnt].p=v; edge[cnt].next=head[u]; edge[cnt].w=w; head[u]=cnt++; } int Guass(){ int i, j, k, col, max_r; for (k=0, col=0; k<equ&&col<var; ++k, ++col){ max_r=k; FO(i,k+1,equ) if (fabs(a[i][col])>fabs(a[max_r][col])) max_r=i; if (fabs(a[max_r][col])<eps) return 0; if (k!=max_r) {FO(j,col,var) swap(a[k][j],a[max_r][j]); swap(x[k],x[max_r]);} x[k]/=a[k][col]; FO(j,col+1,var) a[k][j]/=a[k][col]; a[k][col]=1; FO(i,0,equ) if (i!=k) { x[i]-=x[k]*a[i][col]; FO(j,col+1,var) a[i][j]-=a[k][j]*a[i][col]; a[i][col]=0; } } return 1; } int main () { int n, m, u, v, w; double ans=0; scanf("%d%d",&n,&m); equ=var=n; while (m--) { scanf("%d%d%d",&u,&v,&w); --u; --v; if (u!=v) add_edge(u,v,w), add_edge(v,u,w), ++dee[v]; else add_edge(u,v,w); ++dee[u]; } FO(i,0,32) { mem(a,0); mem(x,0); FO(j,0,n-1) { a[j][j]=dee[j]; for (int k=head[j]; k; k=edge[k].next) { v=edge[k].p; w=edge[k].w; if (w&(1<<i)) {a[j][v]+=1; x[j]+=1;} else a[j][v]-=1; } } a[n-1][n-1]=1; Guass(); ans+=(x[0]*(1<<i)); } printf("%.3f\n",ans); return 0; }