[BZOJ2337][HNOI2011]XOR和路径(概率期望dp+高斯消元)

245 篇文章 0 订阅
211 篇文章 0 订阅

题目描述

传送门

题解

按位分解,统计每一位为0和为1的概率,最后乘上权值就行了
算概率的话用高斯消元
时间复杂度 O(30(2n)3) ,很不科学对不对我也是这么觉得

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 205

int n,m;
int tot,point[N],nxt[N*100],v[N*100],c[N*100];
double d[N],a[N][N],b[N],f[N],ans;

void add(int x,int y,int z)
{
    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;
}
void gauss()
{
    for (int i=1;i<=n<<1;++i)
    {
        int num=i;
        for (int j=i+1;j<=n<<1;++j)
            if (fabs(a[j][i])>fabs(a[num][i])) num=i;
        if (num!=i)
        {
            for (int j=1;j<=n<<1;++j) swap(a[i][j],a[num][j]);
            swap(b[i],b[num]);
        }
        for (int j=i+1;j<=n<<1;++j)
            if (fabs(a[j][i]))
            {
                double t=a[j][i]/a[i][i];
                for (int k=1;k<=n<<1;++k) a[j][k]-=a[i][k]*t;
                b[j]-=b[i]*t;
            }
    }
    for (int i=n<<1;i>=1;--i)
    {
        for (int j=i+1;j<=n;++j) b[i]-=a[i][j]*f[j];
        f[i]=b[i]/a[i][i];
    }
}
double solve(int bit)
{
    memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(f,0,sizeof(f));
    for (int i=1;i<=n;++i)
    {
        a[i][i]=1.0;a[n+i][n+i]=1.0;
        for (int j=point[i];j;j=nxt[j])
        {
            int x=(c[j]>>bit)&1;
            if (v[j]==n) continue;
            if (!x)
            {
                a[i][v[j]]-=1/d[v[j]];
                a[n+i][n+v[j]]-=1/d[v[j]];
            }
            else
            {
                a[i][n+v[j]]-=1/d[v[j]];
                a[n+i][v[j]]-=1/d[v[j]];
            }
        }
    }b[1]=1.0;
    gauss();
    return f[n<<1];
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;++i)
    {
        int x,y,z;scanf("%d%d%d",&x,&y,&z);
        d[x]+=1.0;
        if (x!=y) d[y]+=1.0;
        add(x,y,z);
        if (x!=y) add(y,x,z);
    }
    for (int i=0;i<29;++i)
    {
        double now=solve(i);
        ans+=now*(1<<i);
    }
    printf("%.3lf\n",ans);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值