BZOJ 2337 XOR和路径

按位考虑。f[i]表示从i->n为1的期望。

注意并不用记两个,因为1-f[i]就是i->n为0的期望。

列出式子高消。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxv 150
#define maxe 20050
#define eps 1e-9
using namespace std;
int n,m,nume=1,g[maxv],x,y,z,d[maxv];
double a[maxv][maxv],ans=0;
struct edge
{
    int v,bit[32],nxt;
}e[maxe];
void addedge(int u,int v,int w)
{
    e[++nume].v=v;e[nume].nxt=g[u];g[u]=nume;
    int ret=0;
    while (w) {e[nume].bit[ret]=w&1;w>>=1;ret++;}
}
void Gauss()
{
    for (int i=1;i<=n;i++)
    {
        int id=i;double st=-1.0;
        for (int j=i;j<=n;j++) 
            if (fabs(a[j][i])+eps>st) 
                {st=fabs(a[j][i]);id=j;}
        if (id!=i) for (int j=1;j<=n+1;j++) swap(a[id][j],a[i][j]);
        double t=a[i][i];
        for (int j=1;j<=n+1;j++) a[i][j]/=t;
        for (int j=1;j<=n;j++)
        {
            if (j==i) continue;
            double t=a[j][i]/a[i][i];
            for (int k=1;k<=n+1;k++) a[j][k]-=t*a[i][k];
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);d[x]++;if (x!=y) d[y]++;
        addedge(x,y,z);if (x!=y) addedge(y,x,z);
    }
    for (int t=0;t<=30;t++)
    {
        for (int i=1;i<=n+1;i++)
            for (int j=1;j<=n+1;j++)
                a[i][j]=0;
        for (int i=1;i<=n-1;i++)
        {
            for (int j=g[i];j;j=e[j].nxt)
            {
                int v=e[j].v;
                if (e[j].bit[t]) {a[i][v]+=1.0/d[i];a[i][n+1]+=1.0/d[i];}
                else a[i][v]-=1.0/d[i];
            }
            a[i][i]+=1.0;
        }
        a[n][n]=1.0;
        Gauss();
        ans+=a[1][n+1]*(1<<t);
    }
    printf("%.3f
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/ziliuziliu/p/6564528.html