2018 Multi-University Training Contest 1 08

题意

\(n\)\(a_1,\ a_2,\ ...,\ a_n\)。定义 \(f(a,\ l,\ r)\ =\ min\{i\ |\ a_i\ \geq\ a_j\ (l\ \leq\ j\ \leq\ r)\}\)\(F(b_1,\ b_2,\ ...,\ b_n)\ =\ [\forall\ 1\ \leq\ l\ \leq\ r\ \leq\ n,\ f(a,\ l,\ r)\ =\ f(b,\ l,\ r)]\ \times\ (\sum_{i\ =\ 1}^n\ b_i)\)
问如果 \(b\) 中每个数均为 \([0,\ 1]\) 中独立的随机的实数,则 \(F(b)\) 的期望是多少,模 \(10^9\ +\ 7\) 输出。

\(1\ \leq\ n\ \leq\ 10^6\)

做法1

每次从 \(a\) 中找到当前的 \(f(a,\ l,\ r)\),然后递归下去,从 \(l\ =\ 1,\ r\ =\ n\) 开始递归,建出树。如果 \(b\) 的树与 \(a\) 的树一样则 \(F(b)\) 不为 \(0\)
由于 \(b\) 中存在相等的数的概率为 \(0\),所以可以考虑对于任意的一个 \(0\ \leq\ x_1\ <\ x_2\ <\ ...\ <\ x_n\ \leq\ 1\) 和排列 \(p_1,\ p_2,\ ...,\ p_n\),可以得到一个 \(b\),其中 \(b_i\ =\ x_{p_i}\)
考虑一个 \(p\) 对应的所有的 \(x\),其期望和为 \(\frac{n}{2}\)。于是问题就变成合法 \(p\) 的概率是多少。
合法 \(p\) 的个数就是对 \(a\) 建出的树的拓扑序个数。

代码

#include <bits/stdc++.h>

#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif

#ifdef __WIN32
#define LLFORMAT "I64"
#else
#define LLFORMAT "ll"
#endif

using namespace std;

const int maxn = 1e6 + 10, lgn = 21, mod = 1e9 + 7;

template <int input_SZ, int output_SZ> struct IO {
	char s[input_SZ], t[output_SZ], *a, *b;

	IO() { fread(s, 1, input_SZ, stdin); a = s; b = t; }
	~IO() { fwrite(t, 1, b - t, stdout); }

	char nextchar(char c) {
		return *a++;
	}

	int nextint() {
		while(*a != '-' && (*a < '0' || *a > '9')) ++a;
		bool flag = 0; int x = 0;
		if(*a == '-') ++a, flag = 1;
		while(*a >= '0' && *a <= '9') x = x * 10 + *a++ - '0';
		if(flag) x = -x;
		return x;
	}

	long long nextll() {
		while(*a != '-' && (*a < '0' || *a > '9')) ++a;
		bool flag = 0; long long x = 0;
		if(*a == '-') ++a, flag = 1;
		while(*a >= '0' && *a <= '9') x = x * 10 + *a++ - '0';
		if(flag) x = -x;
		return x;
	}

	void outchar(char c) {
		*b++ = c;
		if(b - t > output_SZ - 25) { fwrite(t, 1, b - t, stdout); b = t; }
		return;
	}

	template<typename T> void outnum(T x) {
		if(!x) { *b++ = '0'; return; }
		if(x < 0) *b++ = '-', x = -x;
		static char s[20], *a;
		a = s;
		while(x) {
			T y = x / 10;
			*a++ = x - y * 10 + '0';
			x = y;
		}
		while(a != s) *b++ = *--a;
		if(b - t > output_SZ - 25) { fwrite(t, 1, b - t, stdout); b = t; }
		return;
	}

	template<typename T> void outnum(T x, char c) {
		return outnum(x), outchar(c);
	}
};

IO<(1 << 25) | 10, (1 << 24) | 10> io;

int a[maxn], st[maxn][lgn], LOG[maxn], n, T, q[maxn], fnt, rar, l[maxn], r[maxn], par[maxn], sz[maxn], dp[maxn], fac[maxn], ifac[maxn];

int pow_mod(int x, int n = mod - 2) { int y = 1; while(n) { if(n & 1) y = (long long) y * x % mod; x = (long long) x * x % mod; n >>= 1; } return y; }

int cmax(int i, int j) { return a[i] < a[j] ? j : i; }

int Q(int l, int r) {
	if(l == r) return st[l][0];
	int lg = LOG[r - l + 1];
	return cmax(st[l][lg], st[r - (1 << lg) + 1][lg]);
}

void PB(int s, int t, int f = -1) {
	par[rar] = f;
	l[rar] = s;
	r[rar] = t;
	sz[rar] = 0;
	dp[rar] = 1;
	q[rar] = Q(s, t);
	++rar;
	return;
}

int C(int n, int m) { return n < m || m < 0 ? 0 : (long long) fac[n] * ifac[m] % mod * ifac[n - m] % mod; }

void solve() {
	n = io.nextint();
	for (int i = 1; i <= n; ++i) a[i] = io.nextint(), st[i][0] = i;
	for (int lg = 1; lg < lgn; ++lg) {
		int l = 1 << lg - 1;
		for (int i = 1; i + l <= n; ++i) st[i][lg] = cmax(st[i][lg - 1], st[i + l][lg - 1]);
	}
	fnt = rar = 0;
	PB(1, n);
	while(fnt != rar) {
		int l = ::l[fnt], r = ::r[fnt], i = ::q[fnt]; ++fnt;
		if(l < i) PB(l, i - 1, fnt - 1);
		if(i < r) PB(i + 1, r, fnt - 1);
	}
	for (int i = rar - 1; i; --i) {
		++sz[i];
		int j = par[i];
		dp[j] = (long long) dp[j] * C(sz[j] + sz[i], sz[i]) % mod * dp[i] % mod;
		sz[j] += sz[i];
	}
	io.outnum((int)((long long) dp[0] * n % mod * ifac[n] % mod * ifac[2] % mod), '\n');
	return;
}

int main() {
	for (int i = 2; i < maxn; ++i) LOG[i] = LOG[i >> 1] + 1;
	for (int i = fac[0] = 1; i < maxn; ++i) fac[i] = (long long) fac[i - 1] * i % mod;
	ifac[maxn - 1] = pow_mod(fac[maxn - 1]);
	for (int i = maxn - 1; i; --i) ifac[i - 1] = (long long) ifac[i] * i % mod;
	T = io.nextint();
	while(T--) solve();
	return 0;
}
posted @ 2018-09-08 11:34  King_George  阅读(142)  评论(0编辑  收藏  举报