生活随笔
收集整理的這篇文章主要介紹了
洛谷 P3211 [HNOI2011]XOR和路径(推dp+高斯消元)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
首先,異或的話直接討論不好討論,那么我們可以按位討論,對于每一位討論出來一個結果,然后將結果相加就好了。
然后考慮怎么討論一位上的結果。
我們可以設出來一個dp方程:f(i)表示i到n的異或和期望值,則初始狀態為f(n)=0
dp轉移方程就是:其中weight(u,v)代表(u,v)的那一位的值
f(v)=∑(u,v)∈Ef(u)/degree(v) weight(u,v)=0
f(v)=∑(u,v)∈E(1?f(u))/degree(v) weight(u,v)=1
則對于每一個i,都會有一個線性方程:
f[i]=f[j1]/degree[i]+(1?f[j2])/degree[i]+......
然后預處理出矩陣來,高斯消元即可。
代碼:
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
inline int read(){
int x=
0;
char ch=
' ';
int f=
1;
while(ch<
'0'||ch>
'9')ch=getchar();
if(ch==
'-'){f=-
1;ch=getchar();}
while(ch>=
'0'&&ch<=
'9')x=x*
10+ch-
'0',ch=getchar();
return x*f;
}
struct edge{
int to,next,w;
}e[
20001];
int n,m,tot;
int head[
101];
int in[
101];
double a[
101][
101];
void gauss(){
for(
int i=
1;i<=n;i++){
int mx=i;
while(!a[mx][i])mx++;
if(i!=mx)swap(a[i],a[mx]);
double mul=a[i][i];
for(
int j=i;j<=n+
1;j++)a[i][j]/=mul;
for(
int k=
1;k<=n;k++){
if(k!=i&&a[k][i]){mul=a[k][i];
for(
int j=i;j<=n+
1;j++){a[k][j]-=mul*a[i][j];}}}}
}
inline void addedge(
int x,
int y,
int l){e[++tot].to=y;e[tot].next=head[x];e[tot].w=l;head[x]=tot;in[y]++;
}
int main(){n=read();m=read();
for(
int i=
1;i<=m;i++){
int x=read(),y=read(),l=read();
if(x!=y)addedge(x,y,l),addedge(y,x,l);
else addedge(x,y,l);}
double ans=
0;
for(
int k=
0;k<=
30;k++){
memset(a,
0,
sizeof(a));
for(
int x=
1;x<n;x++){a[x][x]=
1.0;
for(
int i=head[x];i;i=e[i].next){
int u=e[i].to;
if((e[i].w>>k)&
1){a[x][u]+=
1.0/in[x];a[x][n+
1]+=
1.0/in[x];}
else{a[x][u]-=
1.0/in[x];}}}a[n][n]=
1.0;gauss();ans+=a[
1][n+
1]*
1.0*(
1<<k);}
printf(
"%.3lf",ans);
return 0;
}
轉載于:https://www.cnblogs.com/stone41123/p/7581240.html
總結
以上是生活随笔為你收集整理的洛谷 P3211 [HNOI2011]XOR和路径(推dp+高斯消元)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。