P3211 [HNOI2011]XOR和路徑
阿新 • • 發佈:2020-11-27
Solution
我們可以發現這個題和遊走很像(雖然遊走是HNOI2013,這個是HNOI2011吧)
但是這個題是要求異或和,每一位是互不干擾的,再加上期望的線性性,所以考慮每一位單獨計算。
我們設 \(f_i\) 表示從 \(i\) 到 \(n\) 路徑這一位異或和為 \(1\) 的概率,那麼我們可以顯然的得到轉移方程:
(其中 \(w_{u,v}\) 表示 \(\langle u,v\rangle\)
前面的 \(\sum\) 表示要在 \(v\) 中找 \(0\) 的概率,後面的表示要在 \(v\) 中找 \(1\) 的概率。
我們發現這個方程是有後效性的,所以還要繼續考慮。發現進一步轉化可以得到:
\[-\sum_{v\in w_{u,v} 此位為 1}\frac 1{d_u}=-f_u+\sum_{v\in w_{u,v} 此位為 0} \frac {f_v}{d_u}-\sum_{v\in w_{u,v} 此位為 1} \frac {f_v}{d_u} \]哦~這長得很像 \(n-1\)
( 因為到達 \(n\) 的時候就停止了,所以 \(f_n=0\) ,在計算的時候不考慮)
再簡單的提一下計算答案: 設當前位為 \(i\) ,那就 \(ans+=f_1\times 2^i\) 即可。
注意:一個自環只能增加一條邊,重邊在累加方程係數的時候都要算上。
時間複雜度為 \(O(n^3\log w)\)
完結撒花
你不會以為這就完了吧(⊙_⊙)
為什麼是從 \(u\) 到 \(n\) 逆推呢?我相信只有我一個蒟蒻感到疑惑,但是還是要說一下。
因為異或和不為 \(1\) 的概率是 \(1-f_u\) ,但是正推此時的含義是: \(1\)
正式完結撒發。
Code
#include<bits/stdc++.h>
#define re register
using namespace std;
const int N=110;
const double eps=1e-9;
int n,m,head[N],cnt,d[N],pw[N];
double a[N][N],f[N],ans;
struct edge{
int to,nxt,w;
}e[N*N<<1];
inline int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
return x*f;
}
inline void add(int u,int v,int w){
e[++cnt].to=v;
e[cnt].w=w;
e[cnt].nxt=head[u];
head[u]=cnt;
d[v]++;
}
inline void Gauss(){
for(re int i=1;i<n;i++)
for(re int j=i+1;j<=n;j++){
double tmp=a[j][i]/a[i][i];
for(re int k=1;k<=n+1;k++) a[j][k]-=a[i][k]*tmp;
}
for(re int i=n;i;i--){
f[i]=a[i][n+1]/a[i][i];
for(re int j=i-1;j;j--) a[j][n+1]-=a[j][i]*f[i];
}
}
int main(){
n=read(); m=read();
memset(head,-1,sizeof(head));
pw[0]=1;
for(re int i=1;i<=30;i++) pw[i]=pw[i-1]*2;
for(re int i=1,u,v,w;i<=m;i++){
u=read(); v=read(); w=read();
add(u,v,w); if(u!=v) add(v,u,w);
}
for(re int i=0;i<=30;i++){
memset(a,0,sizeof(a)); a[n][n]-=1.0;
for(re int u=1;u<n;u++){
a[u][u]=-1;
for(re int j=head[u];j!=-1;j=e[j].nxt){
int v=e[j].to;
if(~e[j].w&pw[i]) a[u][v]+=1.0/d[u];
else a[u][n+1]-=1.0/d[u],a[u][v]-=1.0/d[u];
}
}
Gauss();
ans+=f[1]*pw[i];
}
printf("%.3lf\n",ans);
return 0;
}
小彩蛋:題目描述中的第一段的題也是真實出現的,就是介個。