BZOJ 2337 XOR和路径(概率DP)

时间:2023-03-09 20:35:57
BZOJ 2337 XOR和路径(概率DP)

求点1到点n经过的路径权值异或和的期望。

考虑按位计算,对于每一位来说,令dp[i]表示从i到n的异或和期望值。

那么dp[i]=sum(dp[j]+1-dp[k]).如果w(i,j)这一位为0,如果w(i,k)这一位为1.边界为dp[n][n]=0.

那么求解每个方程组就得到了每一位的贡献。另外注意自环的出理就ok了。

# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... struct Edge{int p, next, w;}edge[];
int head[N], cnt=, dee[N];
double a[N][N], x[N];
int equ, var; void add_edge(int u, int v, int w){
edge[cnt].p=v; edge[cnt].next=head[u]; edge[cnt].w=w; head[u]=cnt++;
}
int Guass(){
int i, j, k, col, max_r;
for (k=, col=; k<equ&&col<var; ++k, ++col){
max_r=k;
FO(i,k+,equ) if (fabs(a[i][col])>fabs(a[max_r][col])) max_r=i;
if (fabs(a[max_r][col])<eps) return ;
if (k!=max_r) {FO(j,col,var) swap(a[k][j],a[max_r][j]); swap(x[k],x[max_r]);}
x[k]/=a[k][col];
FO(j,col+,var) a[k][j]/=a[k][col];
a[k][col]=;
FO(i,,equ) if (i!=k) {
x[i]-=x[k]*a[i][col];
FO(j,col+,var) a[i][j]-=a[k][j]*a[i][col];
a[i][col]=;
}
}
return ;
}
int main ()
{
int n, m, u, v, w;
double ans=;
scanf("%d%d",&n,&m);
equ=var=n;
while (m--) {
scanf("%d%d%d",&u,&v,&w);
--u; --v;
if (u!=v) add_edge(u,v,w), add_edge(v,u,w), ++dee[v];
else add_edge(u,v,w);
++dee[u];
}
FO(i,,) {
mem(a,); mem(x,);
FO(j,,n-) {
a[j][j]=dee[j];
for (int k=head[j]; k; k=edge[k].next) {
v=edge[k].p; w=edge[k].w;
if (w&(<<i)) {a[j][v]+=; x[j]+=;}
else a[j][v]-=;
}
}
a[n-][n-]=;
Guass();
ans+=(x[]*(<<i));
}
printf("%.3f\n",ans);
return ;
}