【Topcoder SRM 641】BitToggler 期望 高斯消元

有一个长度为n的01数列a和一个指针,每次随机将指针移至j,并将aj取反,花费为|i - j|,当数列全0或全1停止,求期望花费。n <= 20

使用期望的线性性,每次只统计i到j的贡献,这样其他位置就没有区分了,压个状态就可以消元了。


#include 
#include 
#include 
#include 
#include 
#include 
#define Rep(i, x, y) for (int i = x; i <= y; i ++)
#define Dwn(i, x, y) for (int i = x; i >= y; i --)
#define RepE(i, x) for(int i = pos[x]; i; i = g[i].nex)
#define eps 0.000000001
using namespace std;
typedef long long LL;
typedef double DB;
const int M = 330;
int n, m, Q;
DB a[M][M], sum;
vector  ans;
void PreWork() {
	m = (n - 1) * 16;
	DB p1 = 1.0 / n;
	Rep(i, 0, 1) {
		Rep(j, 0, 1) {
			Rep(k, 0, n - 2) {
				int s = (k * 4 + i * 2 + j) * 4;
				if (!s || s == (n - 2) * 16 + 12) {
					Rep(t, 0, 3) a[s + t][s + t] = 1;
					continue ;
				}
				Rep(t, 0, 3) {
					a[s + t][s + t] = 1;
					a[s + t][s ^ 8] = -p1;
					a[s + t][(s ^ 4) + 1] = -p1;
					if (k) a[s + t][s - 14] = -p1 * k;
					if (k < n - 2) a[s + t][s + 19] = -p1 * (n - 2 - k);
				}
				a[s][m] = p1;
			}
		}
	}
	Rep(i, 1, m - 1) {
		int k = i;
		while (k < m && fabs(a[k][i]) < eps) k ++;
		if (k >= m) { continue ; }
		Rep(j, 1, m) swap(a[i][j], a[k][j]);
		Rep(j, 1, m - 1) if (i != j && a[j][i]) {
			DB z = a[j][i] / a[i][i];
			Rep(x, 1, m) a[j][x] -= z * a[i][x];
		}
	}
}
class BitToggler {
public:
	vector  expectation(int n0, vector  bits, vector  pos) {
		Q = bits.size(), n = n0;
		PreWork();
		Rep(T0, 0, Q - 1) {
			sum = 0; int num = 0, k, s;
			Rep(i, 0, n - 1) num += (bits[T0][i] == '1');
			Rep(i, 0, n - 1) {
				Rep(j, 0, n - 1) if (i != j) {
					if (i == pos[T0]) k = 0;
					else if (j == pos[T0]) k = 1;
					else if (bits[T0][ pos[T0] ] == '0') k = 2;
					else k = 3;
					bool x1 = (bits[T0][i] == '1'), x2 = (bits[T0][j] == '1');
					s = ((num - x1 - x2) * 4 + x1 * 2 + x2) * 4 + k;
					sum += a[s][m] / a[s][s] * abs(i - j);
				}
			}
			ans.push_back(sum);
		}
		return ans;
	}
};


你可能感兴趣的:(数学,Topcoder)