zoukankan      html  css  js  c++  java
  • 洛谷 P3211 [HNOI2011]XOR和路径(推dp+高斯消元)

    传送门
    首先,异或的话直接讨论不好讨论,那么我们可以按位讨论,对于每一位讨论出来一个结果,然后将结果相加就好了。
    然后考虑怎么讨论一位上的结果。
    我们可以设出来一个dp方程:f(i)表示i到n的异或和期望值,则初始状态为f(n)=0
    dp转移方程就是:其中weight(u,v)代表(u,v)的那一位的值
    f(v)=(u,v)Ef(u)/degree(v) weight(u,v)=0
    f(v)=(u,v)E(1f(u))/degree(v) weight(u,v)=1
    则对于每一个i,都会有一个线性方程:
    f[i]=f[j1]/degree[i]+(1f[j2])/degree[i]+......
    然后预处理出矩阵来,高斯消元即可。
    代码:

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0;char ch=' ';int f=1;
        while(ch<'0'||ch>'9')ch=getchar();
        if(ch=='-'){
            f=-1;ch=getchar();
        }
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    struct edge{
        int to,next,w;
    }e[20001];
    int n,m,tot;
    int head[101];
    int in[101];
    double a[101][101];
    void gauss(){
        for(int i=1;i<=n;i++){
            int mx=i;
            while(!a[mx][i])mx++;
            if(i!=mx)swap(a[i],a[mx]);
            double mul=a[i][i];
            for(int j=i;j<=n+1;j++)a[i][j]/=mul;
            for(int k=1;k<=n;k++){
                if(k!=i&&a[k][i]){
                    mul=a[k][i];
                    for(int j=i;j<=n+1;j++){
                        a[k][j]-=mul*a[i][j];
                    }
                }
            }
        }
    }
    inline void addedge(int x,int y,int l){
        e[++tot].to=y;e[tot].next=head[x];e[tot].w=l;head[x]=tot;in[y]++;
    }
    int main(){
        n=read();m=read();
        for(int i=1;i<=m;i++){
            int x=read(),y=read(),l=read();
            if(x!=y)addedge(x,y,l),addedge(y,x,l);
            else addedge(x,y,l);
        }
        double ans=0;
        for(int k=0;k<=30;k++){
            memset(a,0,sizeof(a));
            for(int x=1;x<n;x++){
                a[x][x]=1.0;
                for(int i=head[x];i;i=e[i].next){
                    int u=e[i].to;
                    if((e[i].w>>k)&1){
                        a[x][u]+=1.0/in[x];a[x][n+1]+=1.0/in[x];
                    }
                    else{
                        a[x][u]-=1.0/in[x];
                    }
                }
            }
            a[n][n]=1.0;
            gauss();
            ans+=a[1][n+1]*1.0*(1<<k);
        }
        printf("%.3lf",ans);
        return 0;
    }
  • 相关阅读:
    Ubuntu
    SSH
    Markdown
    Mac OS 上的一些骚操作
    Linux Bash
    JConsole
    IDEA
    Groovy
    Github
    Git
  • 原文地址:https://www.cnblogs.com/stone41123/p/7581240.html
Copyright © 2011-2022 走看看