• 【概率DP/高斯消元】BZOJ 2337:[HNOI2011]XOR和路径


    2337: [HNOI2011]XOR和路径

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 682  Solved: 384
    [Submit][Status][Discuss]

    Description


      几乎是一路看题解过来了。。
      拖了一个星期的题目- -
      已然不会概率DP(说得好像什么时候会过一样),高斯消元(打一次copy一遍)。
      发现异或题目的新解决方法:按位处理。。
      发现DP新方法:高斯消元。
      f[k][i]代表第k位权值起点为i到终点时答案的期望值。
      则对一条边<i,j>有两种转移:当边权为0,f[k][j]/deg[i].当边权为1,(1-f[k][j])/deg[i]。
      由于是一个无向图。
      topo DP很不好搞。
      只能高斯消元。
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 
     6 using namespace std;
     7 
     8 struct edge{
     9     int to,c,last;
    10 }edge[20001];
    11 
    12 int last[101],tot=0,in[101],n;
    13 
    14 double f[120][120],V[120];
    15 
    16 inline int read()
    17 {
    18     int x=0;char ch=getchar();
    19     while(ch<'0'||ch>'9')ch=getchar();
    20     while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
    21     return x;
    22 }
    23 
    24 void add(int u,int v,int c)
    25 {
    26     edge[++tot].to=v,edge[tot].last=last[u],edge[tot].c=c,last[u]=tot;
    27     in[u]++;
    28 }
    29 
    30 void chan(int a,int b)
    31 {
    32     for(int i=1;i<=n+1;i++)
    33         swap(f[a][i],f[b][i]);
    34 }
    35 
    36 double gauss()
    37 {
    38     for(int i=1;i<=n;i++)
    39     {
    40         if(!f[i][i])
    41         {
    42             for(int j=i+1;j<=n;j++)
    43                 if(f[i][j])
    44                     chan(i,j);
    45         }
    46         for(int j=1;j<=n;j++)
    47         {
    48             if(i==j)continue;
    49             double xi=f[j][i]/f[i][i];
    50             for(int k=1;k<=n+1;k++)f[j][k]-=xi*f[i][k];
    51         }
    52     }
    53     return f[1][n+1]/f[1][1];
    54 }
    55 
    56 int main()
    57 {
    58     int m,u,v,c;
    59     n=read(),m=read();
    60     for(int i=1;i<=m;i++)
    61     {
    62         u=read();v=read();c=read();
    63         add(u,v,c);
    64         if(u!=v)add(v,u,c);
    65     }
    66     for(int i=0;i<31;i++) 
    67     {
    68         for(int j=1;j<n;j++)
    69         {
    70             f[j][j]=1;
    71             for(int k=last[j];k;k=edge[k].last)
    72             {
    73                 if(edge[k].c&(1<<i))f[j][edge[k].to]+=(double)1.0/in[j],f[j][n+1]+=(double)1.0/in[j];
    74                 else f[j][edge[k].to]-=(double)1.0/in[j];
    75             }
    76         }
    77         f[n][n]=1;
    78         V[i]=gauss();
    79         memset(f,0,sizeof(f));
    80     }
    81     double ans=0;
    82     int cnt=1;
    83     for(int i=0;i<31;i++)ans+=cnt*V[i],cnt*=2;
    84     printf("%.3lf",ans);
    85     return 0;
    86 }
    View Code
  • 相关阅读:
    2020系统综合实践 第6次实践作业
    2020系统综合实践 第5次实践作业
    2020系统综合实践 第4次实践作业
    2020系统综合实践 第3次实践作业
    2020系统综合实践 第2次实践作业
    2020系统综合实践 第1次实践作业
    2019 SDN大作业
    2019 SDN上机第7次作业
    软工实践个人总结
    第03组 Beta冲刺(5/5)
  • 原文地址:https://www.cnblogs.com/tuigou/p/4899230.html
Copyright © 2020-2023  润新知