2337: [HNOI2011]XOR和路径 高斯消元解期望方程 概率与期望DP

来源:互联网 发布:顾家北和慎小嶷 知乎 编辑:程序博客网 时间:2024/06/05 01:02

居然没被卡精度,高斯消元居然一边写对了,sb错误居然没犯。。
如此傻逼的我也能1A真是感动。

因为要求的是xor的期望,我们可以按位计算每位的期望再相加。
考虑每一位,我们令d[i]表示点i的出度,我们令f[i]表示从i走到n这一位的xor和为1的概率,那么有

f[i]=j=1d[i]f[j]d[i](edge(i,j)=0),1f[j]d[i](edge(i,j)=1)

玛雅我写的式子好傻逼意会一下就好了
然后我们可以高斯消元来解这个方程。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#define N 105#define M 10005#define eps 1e-8using namespace std;int n,m,cnt;double ans,a[N][N];int head[N],d[N];int next[M<<1],list[M<<1],key[M<<1];inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}inline void insert(int x,int y,int z){    d[x]++;    next[++cnt]=head[x];    head[x]=cnt;    list[cnt]=y;    key[cnt]=z;}inline void Gauss(){    int y;    for (int i=1;i<n;i++)    {        for (y=i;y<n;y++)            if (fabs(a[y][i])>eps) break;        if (y>=n) continue;        if (y!=i)            for (int j=1;j<=n+1;j++) swap(a[i][j],a[y][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)            {                double t=a[j][i];                for (int k=1;k<=n+1;k++)                    a[j][k]-=a[i][k]*t;            }    }}int main(){    n=read(); m=read();    for (int i=1;i<=m;i++)    {        int u=read(),v=read(),w=read();        insert(u,v,w);         if (u!=v) insert(v,u,w);    }    for (int k=0;k<=30;k++)    {        memset(a,0,sizeof(a));        for (int i=1;i<=n;i++) a[i][i]+=(double)d[i];        for (int x=1;x<n;x++)            for (int i=head[x];i;i=next[i])                if (key[i]&(1<<k)) a[x][list[i]]+=1.0,a[x][n+1]+=1.0;                else a[x][list[i]]-=1.0;        Gauss();        ans+=a[1][n+1]*(1<<k);    }    printf("%.3lf\n",ans);    return 0;}
0 0
原创粉丝点击