【HNOI2011】XOR和路径

pre.cjk { font-family: "Droid Sans Fallback", monospace }
p { margin-bottom: 0.25cm; line-height: 120% }
a:link { }

和期望有关的题一脸懵逼QAQ
题目要求的是异或和的期望,所以就把二进制的每一位都搞一遍,最后答案就是每一位的期望和。
然后对于每一位,推出一个很鬼畜的DP方程:f[i]表示i这个点到n的概率。

f[n][n]=1;然后枚举i,枚举i连的每个点,如果这条路的边权为1(这里指的是二进制)f[i]+=(1-f[j])/in[i]。否则f[i]+=f[j]/in[i],in[i]表示的是每个点连接的边的数量。
这里需要注意,自环的边只能加一条,in也只能+1。
 1 #include<set>
 2 #include<map>
 3 #include<queue>
 4 #include<stack>
 5 #include<ctime>
 6 #include<cmath>
 7 #include<string>
 8 #include<vector>
 9 #include<cstdio>
10 #include<cstdlib>
11 #include<cstring>
12 #include<iostream>
13 #include<algorithm>
14 using namespace std;
15 struct data{
16   int nex,to,w;
17 }e[20010];
18 int n,head[110],edge=0;
19 double a[110][110],in[110];
20 void add(int from,int to,int w){
21   e[++edge].nex=head[from];
22   e[edge].to=to;
23   e[edge].w=w;
24   head[from]=edge;
25 }
26 void gauss(){
27   for(int i=1;i<=n;i++){
28     int t=i;
29     while(!a[t][i] && t<=n) t++;
30     if(t>n) continue;
31     for(int j=1;j<=n+1;j++) swap(a[t][j],a[i][j]);
32     double k=a[i][i];
33     for(int j=i;j<=n+1;j++) a[i][j]/=k;
34     for(int j=1;j<=n;j++)
35       if(j!=i && a[j][i]){
36     k=a[j][i];
37     for(int p=i;p<=n+1;p++)
38       a[j][p]-=k*a[i][p];
39       }
40   }
41 }
42 int main()
43 {
44   freopen("!.in","r",stdin);
45   freopen("!.out","w",stdout);
46   int m,x,y,z;
47   double ans=0.0;
48   scanf("%d%d",&n,&m);
49   for(int i=1;i<=m;i++){
50     scanf("%d%d%d",&x,&y,&z);
51     if(x!=y) add(x,y,z),add(y,x,z),in[x]++,in[y]++;
52     else add(x,y,z),in[x]++;
53   }
54   for(int p=0;p<=30;p++){
55     memset(a,0,sizeof(a));
56     for(int i=1;i<n;i++){
57       a[i][i]=1.0;
58       for(int j=head[i];j;j=e[j].nex)
59     if(e[j].w&(1<<p)) a[i][e[j].to]+=1.0/in[i],a[i][n+1]+=1.0/in[i];
60     else a[i][e[j].to]-=1.0/in[i];
61     }
62     a[n][n]=1.0;
63     gauss();
64     ans+=a[1][n+1]*1.0*(1<<p);
65   }
66   printf("%.3lf",ans);
67   return 0;
68 }


这看起来像一个动态规划,但是这是一个无向图,DP好像跑不了,那怎么办?
对于每一个i,都会有一个线性方程:
f[i]=f[j1]/in[i]+(1-f[j2])/in[i]+......
然后就会发现有n个方程,然后就可以用高斯消元了......简直妙不可言。
时间: 2024-10-16 04:53:15

【HNOI2011】XOR和路径的相关文章

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

2337: [HNOI2011]XOR和路径 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 682  Solved: 384[Submit][Status][Discuss] Description 几乎是一路看题解过来了.. 拖了一个星期的题目- - 已然不会概率DP(说得好像什么时候会过一样),高斯消元(打一次copy一遍). 发现异或题目的新解决方法:按位处理.. 发现DP新方法:高斯消元. f[k][i]代表第k位权值起点为i到终点时答案

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

2337: [HNOI2011]XOR和路径 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1170  Solved: 683 Description Input Output Sample Input Sample Output HINT Source Day2 [分析] 这题终于自己打出来了高斯消元.没有对比代码了... 很心酸啊..调试的时候是完全没有方向的,高斯消元还要自己一步步列式子然后消元解..[为什么错都不知道有时候 这题显然是不能

【BZOJ2337】[HNOI2011]XOR和路径 期望DP+高斯消元

[BZOJ2337][HNOI2011]XOR和路径 Description 题解:异或的期望不好搞?我们考虑按位拆分一下. 我们设f[i]表示到达i后,还要走过的路径在当前位上的异或值得期望是多少(妈呀好啰嗦),设d[i]表示i的度数.然后对于某条边(a,b),如果它的权值是1,那么f[b]+=(1-f[a])/d[a]:如果它的权值是0,那么f[b]+=f[a]/d[a],然后我们移个项,就变成了一堆方程组求解,直接高斯消元. 别忘了f[n]=0! #include <cstdio> #i

【BZOJ】2337: [HNOI2011]XOR和路径

[算法]期望+高斯消元 [题解]因为异或不能和期望同时运算,所以必须转为加乘 考虑拆位,那么对于边权为1取反,边权为0不变. E(x)表示从x出发到n的路径xor期望. 对于点x,有E(x)=Σ(1-E(y))(边权1)||E(y)(边权0)/t[x]  t[x]为x的度. 那么有n个方程,整体乘上t[x]确保精度,右项E(x)移到左边--方程可以各种变形. 每次计算完后*(1<<k)就是贡献. 逆推的原因在于n不能重复经过,而1能重复经过,所以如果计算"来源"不能计算n,

bzoj 2337: [HNOI2011]XOR和路径

Description Input Output Sample Input Sample Output HINT Source Day2 终于把这个史前遗留的坑给填了... 首先异或的话由位无关性,可以按位处理... 那么对于每一位,设f[i]表示从i出发第一次到达n且xor和为1的概率,out[i]为i的出边,那么转移就比较容易了... if(w(i,j)&xxx) f[i]+=(1-f[j)/out[i];// 这条边该位为1,需要xor上0,xor和才为1 else f[i]+=f[j]/

bzoj 2337 [HNOI2011]XOR和路径【高斯消元+dp】

首先,我们发现,因为是无向图,所以相连的点之间是有"依赖性"的,所以不能直接用dp求解. 因为是xor,所以按位处理,于是列线性方程组,设$ x[i] $为点i到n异或和为1的期望,因为从1到n和从n到1一样,所以选择倒着推,即, if(deg[e[i].va]==0) \[ x[u]=\sum_{v}^{v\subset son(u)}\frac{x[v]}{deg[i]} \] else \[ x[u]=\sum_{v}^{v\subset son(u)}\frac{1-x[v])

BZOJ2337 HNOI2011 XOR和路径

将权值用二进制表示,由于到达n就立即停止,我们定义f[i]表示从i到达n的期望值. 那么显然f[n]=0,对于其他情况,我们列出其转移方程: f[i]+=f[x]/deg[i] 若两边连边当前位为0 f[i]+=(1-f[x])/deg[i] 若两边连边当前位为1 然后就有n-1个方程,高斯消元求解,由于必有唯一解,写起来就方便多了. 最终的答案就是f[1]*2^当前位累加和 1 #include<cstdio> 2 #include<cstdlib> 3 #include<

[HNOI2011]XOR和路径

题面 一道期望大火题(表示看了zsy大佬和ycb大佬的题解才过去的orz) 递推期望,因为是异或和,按照正常方法会很难,于是考虑按位DP(套路吧) 设状态的时候需要注意 如果设f[x]表示从1号节点到达x号节点且异或和为1的概率 那么在转移的时候,因为到达n号节点的时候就已经停止,所以f[n]不能转移;而我们又必须求出f[n],因此必须先对除n以外的所有点进行计算,再推到n,这样会很麻烦 于是想到倒着推,设f[x]表示从x号节点到达n号节点且异或和为1的概率,答案为f1,虽然说也不能从f[n]转

【BZOJ2337】Xor和路径(高斯消元)

[BZOJ2337]Xor和路径(高斯消元) 题面 BZOJ 题解 我应该多学点套路: 对于xor之类的位运算,要想到每一位拆开算贡献 所以,对于每一位拆开来看 好了,既然是按位来算 我们就只需要计算从\(1\)号点开始 到\(n\)的路径中,路径的异或和为\(1\)的概率 显然没法算 还是一样的 考虑高斯消元 对于每一个节点\(i\) \[f[i]=\sum_{w(u,i)=1}\frac{1-f[u]}{op[u]}+\sum_{w(u,i)=1}\frac{f[u]}{op[u]}\] 其