zoukankan      html  css  js  c++  java
  • [HNOI2011]XOR和路径 题解

    (f(x)) 表示从 (x) 节点走到 (n) 的期望。有 $$f(x)=sum_{{x,y}}frac{f(y)oplus w(x,y)}{{ m deg}(x)}$$ 由于有后效性,无法 DP 求得。于是可以将其看作未知数,(n) 个点构成 (n)(n) 元一次方程,解方程即可。
    但还是不太好求,考虑期望的线性性,按位处理。
    重新记 (f(x)) 表示当前位的 (x) 走到 (n) 异或和为 (1) 的概率,有 $${ m deg}(x)f(x)=sum_{w(x,y)=1}f(y)+sum_{w(x,y)=0}ig(1-f(y)ig)$$ 最后的答案为 (sumlimits_{t=1}^{32} 2^{t-1}cdot f(1))
    为了消元简便,实际求的过程中我们把方程写成 $$sum_{w(x,y)=0}f(y)-sum_{w(x,y)=1}f(y)-{ m deg}(x)f(x)=-sum_{w(x,y)=1}1$$
    注意自环只用算一次。
    别颓废了……抓紧时间……

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=105,M=10005;
    const double eps=1e-8;
    struct Edge{int to,nxt,w;}e[M<<1];
    int n,m,cnt,head[N],deg[N];
    double ans,a[N][N];
    
    inline void add(int u,int v,int w) {e[++cnt]=(Edge){v,head[u],w};head[u]=cnt;}
    
    void gauss()
    {
        for(int i=1;i<=n;++i)
        {
            int t=i;
            for(int j=i+1;j<=n;++j)
                if(fabs(a[j][i])>fabs(a[t][i])) t=j;
            for(int j=i;j<=n+1;++j) swap(a[t][j],a[i][j]);
            for(int j=n+1;j>=i;--j) a[i][j]/=a[i][i];
            for(int j=1;j<=n;++j)
                if(i!=j)
                    for(int k=n+1;k>=i;--k)
                        a[j][k]-=a[j][i]*a[i][k];
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1,d,b,c;i<=m;++i)
        {
            scanf("%d%d%d",&d,&b,&c);
            if(d==b)
            {
                deg[d]++; add(d,b,c);
            }
            else
            {
                deg[d]++,deg[b]++;
                add(d,b,c); add(b,d,c);
            }
        }
        for(int k=30;~k;--k)
        {
            memset(a,0,sizeof(a));
            for(int u=1;u<n;++u)
            {
                a[u][u]=-deg[u];
                for(int i=head[u];i;i=e[i].nxt)
                {
                    int v=e[i].to,w=(e[i].w>>k)&1;
                    if(w) a[u][v]-=1,a[u][n+1]-=1;
                    else a[u][v]+=1;
                }
            }
            a[n][n]=1; gauss();
            ans+=(1<<k)*a[1][n+1];
        }
        printf("%.3lf",ans);
        return 0;
    }
    
  • 相关阅读:
    c# 如何利用异或运算进行简单加密解密
    五分钟读懂UML类图
    深入浅出UML类图
    WPF中DPI的问题
    .NET调用JAVA的WebService方法
    动态调用WebService(C#) (非常实用)
    Docker入门
    idea开发shell脚本并运行
    SpringEl表达式解析
    Navicate 许可证
  • 原文地址:https://www.cnblogs.com/wzzyr24/p/12315439.html
Copyright © 2011-2022 走看看