BZOJ 2337: [HNOI2011]XOR和路径( 高斯消元 )
一位一位考虑异或结果, f(x)表示x->n异或值为1的概率, 列出式子然后高斯消元就行了
------------------------------------------------------------------
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long double ld;
#define b(i) (1 << (i))
const int maxn = 109;
ld mat[maxn][maxn];
int N, deg[maxn];
struct edge {
int to, w;
edge* next;
} E[20009], *pt = E, *head[maxn];
void AddEdge(int u, int v, int w) {
deg[pt->to = v]++; pt->w = w; pt->next = head[u]; head[u] = pt++;
}
void Init() {
memset(deg, 0, sizeof deg);
int m;
scanf("%d%d", &N, &m); N--;
for(int i = 0; i < m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
u--; v--;
AddEdge(u, v, w);
if(u != v) AddEdge(v, u, w);
}
}
void Work() {
for(int i = 0; i < N; i++) {
int r = i;
for(int j = i; ++j < N; )
if(fabs(mat[j][i]) > fabs(mat[r][i])) r = j;
if(r != i) {
for(int j = 0; j <= N; j++)
swap(mat[i][j], mat[r][j]);
}
for(int j = i; ++j < N; ) {
ld t = mat[j][i] / mat[i][i];
for(int k = i; k <= N; k++)
mat[j][k] -= t * mat[i][k];
}
}
for(int i = N; i--; ) {
for(int j = i; ++j < N; )
mat[i][N] -= mat[i][j] * mat[j][N];
mat[i][N] /= mat[i][i];
}
}
int main() {
Init();
ld ans = 0;
for(int i = 0; i < 30; i++) {
memset(mat, 0, sizeof mat);
for(int j = 0; j < N; j++) {
for(edge* e = head[j]; e; e = e->next) if(e->to != N) {
if(e->w & b(i))
mat[j][e->to]--, mat[j][N]--;
else
mat[j][e->to]++;
} else if(e->w & b(i))
mat[j][N]--;
mat[j][j] -= deg[j];
}
Work();
ans += mat[0][N] * b(i);
}
printf("%.3lf\n", (double) ans);
return 0;
}
------------------------------------------------------------------
2337: [HNOI2011]XOR和路径
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 699 Solved: 390
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
Sample Output
HINT
Source