Description
一个有 (n) 个点,(m) 条边的无向图,边带权
求从 (1) 到 (n) 点的路径异或和的期望
啊,等概率向下一条边走
(n le 100)
Solution
异或和的期望?又 (int) 又 (double) ?
不会处理??
按位处理了解一下!!
定义 (f_i) 表示当前位中从 (i) 到 (n) 点的异或和为 (1) 的期望
然后最后答案直接乘起来就好了
转移就还是很普通
[f_i=frac{1}{d_i}(sumlimits_{w(i,j)=1} (1-f_j)+sumlimits_{w(i,j)=0} f_j)
]
注意异或,所以是反过来的
然后推式子,高斯消元,统计答案就行了呗
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=210;
struct node{
int to,dis,nxt;
}e[N*N*2];
int head[N],cnt;
inline void add(int u,int v,int w)
{
e[++cnt].dis=w; e[cnt].nxt=head[u]; e[cnt].to=v;
return head[u]=cnt,void();
}
int n,m,d[N];
double ans,f[N],a[N][N];
inline void guass(int x)
{
memset(a,0,sizeof(a)); memset(f,0,sizeof(f));
for(int i=1;i<n;++i)
{
a[i][i]=d[i];
for(int j=head[i];j;j=e[j].nxt)
{
int t=e[j].to;
if(e[j].dis&(1<<x)) a[i][t]+=1.0,a[i][n+1]+=1.0;
else a[i][t]-=1.0;
}
}a[n][n]=1;
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;
if(t!=i) swap(a[t],a[i]);
for(int j=i+1;j<=n;++j)
{
double p=a[j][i]/a[i][i];
for(int k=1;k<=n+1;++k) a[j][k]-=p*a[i][k];
}
}
for(int i=n;i>=1;--i)
{
for(int j=i+1;j<=n;++j) a[i][n+1]-=a[i][j]*f[j];
f[i]=a[i][n+1]/a[i][i];
}
return ;
}
signed main()
{
n=read(); m=read();
for(int i=1;i<=m;++i)
{
int x=read(),y=read(),z=read();
add(x,y,z); d[x]++;
if(x==y) continue; d[y]++; add(y,x,z);
}
for(int i=0;i<30;++i)
{
guass(i);
ans+=(1<<i)*f[1];
} printf("%.3lf
",ans);
return 0;
}
}
signed main(){return yspm::main();}
Review
这种无法正常运算的运算可以考虑按位处理啥的
高斯消元一定要开 (double) 呀!!!