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


    2337: [HNOI2011]XOR和路径

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1170  Solved: 683

    Description

    Input

    Output

    Sample Input

    Sample Output

    HINT

    Source

    【分析】

      这题终于自己打出来了高斯消元。没有对比代码了。。。

      很心酸啊。。调试的时候是完全没有方向的,高斯消元还要自己一步步列式子然后消元解。。【为什么错都不知道有时候

      这题显然是不能直接记录异或和然后DP的。

      显然是要拆位的。

      拆位之后f[i][0]表示从i走,走到终点,这一位异或和为0的概率。

      f[i][0]=f[j][0]*p (i->j 这一位边权为0)+f[j][1]*p (i->j 这一位边权为1)

      反之不写了

      f[n][0]=1 f[n][1]=0

      就是(2*n)^2规模的高斯消元。

      然后用f[1][1]乘这一位的贡献加进答案里面就好。

      一开始被卡精,eps太小,后来数组爆一位!!醉了!!

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<cmath>
     7 using namespace std;
     8 #define Maxn 110
     9 #define Maxm 10010
    10 const double eps=1e-60;
    11 
    12 struct node
    13 {
    14     int x,y,c,next;
    15 }t[Maxm*2];
    16 int first[Maxn],len;
    17 double d[Maxn];
    18 void ins(int x,int y,int c)
    19 {
    20     d[x]+=1.0;
    21     t[++len].x=x;t[len].y=y;t[len].c=c;
    22     t[len].next=first[x];first[x]=len;
    23 }
    24 
    25 bool dcmp(double x) {return fabs(x)>eps;}
    26 
    27 double a[2*Maxn][2*Maxn],f[2*Maxn];
    28 void gauss(int n)
    29 {
    30     for(int i=1;i<n;i++)
    31     {
    32         // if(a[i][i]==0) continue;
    33         int t=i;
    34         for(int j=i+1;j<=n;j++) if(fabs(a[j][i])>fabs(a[t][i])) t=j;
    35         if(t!=i)
    36         {
    37             for(int j=1;j<=n;j++) swap(a[i][j],a[t][j]);
    38         }
    39         for(int j=i+1;j<=n;j++)
    40         {
    41             double t=a[j][i]/a[i][i];
    42             if(dcmp(a[j][i]))
    43             {
    44                 for(int k=1;k<=n;k++) a[j][k]-=a[i][k]*t;
    45             }
    46         }
    47     }
    48     for(int i=n-1;i>=1;i--)
    49     {
    50         for(int j=i+1;j<n;j++) a[i][n]+=f[j]*a[i][j];
    51         f[i]=-a[i][n]/a[i][i];
    52     }
    53 }
    54 
    55 int main()
    56 {
    57     int n,m,mx=0;
    58     scanf("%d%d",&n,&m);
    59     len=0;memset(first,0,sizeof(first));
    60     for(int i=1;i<=n;i++) d[i]=0;
    61     for(int i=1;i<=m;i++)
    62     {
    63         int x,y,c;
    64         scanf("%d%d%d",&x,&y,&c);
    65         mx=max(mx,c);
    66         ins(x,y,c);
    67         if(x!=y) ins(y,x,c);
    68     }
    69     int l=0;while((1<<l)<=mx) l++;
    70     double ans=0;
    71     for(int i=0;i<=l;i++)
    72     {
    73         for(int j=0;j<=n+n;j++) for(int k=0;k<=n+n;k++) a[j][k]=0;
    74         for(int j=1;j<n;j++)
    75         {
    76             a[j][j]=1.0;a[j+n][j+n]=1.0;
    77             for(int k=first[j];k;k=t[k].next)
    78             {
    79                 int y=t[k].y;
    80                 if(t[k].c&(1<<i)) a[j][y+n]-=1.0/d[j],a[j+n][y]-=1.0/d[j];
    81                 else a[j][y]-=1.0/d[j],a[j+n][y+n]-=1.0/d[j];
    82             }
    83             a[j][(n<<1)+1]=a[j+n][(n<<1)+1]=0;
    84         }
    85         a[n][n]=1.0;a[n+n][n+n]=1.0;
    86         a[n][(n<<1)+1]=-1.0;a[n<<1][(n<<1)+1]=0;
    87         gauss((n<<1)+1);
    88         // printf("%.10lf
    ",f[n+1]);
    89         ans+=1.0*(1<<i)*f[n+1];
    90     }
    91     printf("%.3lf
    ",ans);
    92     return 0;
    93 }
    View Code

    【怎么说回家前A掉这题还是很兴奋的

    【也说明我能自己打出概率的高斯消元了耶!

    2017-04-22 16:06:09

  • 相关阅读:
    解决Android调用https服务API时出错的问题
    Sqlite 数据库出现database disk image is malformed报错的解决方法
    Bootstrap Chart组件使用分享
    Devexpress TreeList控件绑定显示父子节点对像
    回顾过去的2015展望已经到来的2016年,给自己的一些计划
    1006
    1003
    1001
    Swing用户界面组件-1
    图形程序设计
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6748099.html
Copyright © 2020-2023  润新知