# T1、投票

$n \ (n \leq 2000)$ 个事件，第 $i$ 件事发生的概率为 $p_i$，选出 $k \ (k \leq 2000, 2 | k)$ 件事，求使得发生与不发生的事件数量相同的最大概率；

## $Sol$：

$prf$

$\sum_{for \ all \ situation} \Big[ p_x \cdot \prod_{i = 1} ^ {\frac{k}{2} - 1} p_{a_i} \cdot \prod_{j = 1} ^ {\frac{k}{2}}(1 - p_{b_j}) + (1 - p_x) \cdot \prod_{i = 1} ^ {\frac{k}{2}} p_{b_i} \cdot \prod_{j = 1} ^ {\frac{k}{2} - 1}(1 - p_{a_j})\Big] , \ \{ a_i \} \bigcap \{ b_i \} = \varnothing$

$Q.E.D.$

$f_{i,j}$ 表示前 $i$ 件事恰好发生 $j$ 件的概率，转移是显然的；

## $Source$：

//#pragma GCC optimize(3,"Ofast","inline")
#include <cstdio>
#include <algorithm>
typedef double db;
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 2e3 + 5;
int n, m;
db pre[N][N], suf[N][N], p[N], res;

int main() {
//freopen("in", "r", stdin);
freopen("vote.in", "r", stdin);
freopen("vote.out", "w", stdout);
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i)
scanf("%lf", &p[i]);
std::sort(p + 1, p + 1 + n);
pre[0][0] = 1;
for (int i = 1; i <= m; ++i) {
pre[i][0] = pre[i - 1][0] * (1 - p[i]);
for (int j = 1; j <= i; ++j)
pre[i][j] = pre[i - 1][j - 1] * p[i] + pre[i - 1][j] * (1 - p[i]);
}
std::reverse(p + 1, p + 1 + n);
suf[0][0] = 1;
for (int i = 1; i <= m; ++i) {
suf[i][0] = suf[i - 1][0] * (1 - p[i]);
for (int j = 1; j <= i; ++j)
suf[i][j] = suf[i - 1][j - 1] * p[i] + suf[i - 1][j] * (1 - p[i]);
}
for (int i = 0; i <= m; ++i) {
db tmp = 0;
for (int j = std::max(0, m / 2 - (m - i)); j <= i && j <= m / 2; ++j)
tmp += pre[i][j] * suf[m - i][m / 2 - j];
chk_max(res, tmp);
}
printf("%.7lf\n", res);
return 0;
}


# T2、动态数点

## $Sol$：

$gcd$$\log$ 比较小，直接 $st$ 表可过。

$a_x = a_y$，他们一定会被包含在同一个区间；

## $Source$：

#include <cstdio>
#include <cstring>
#include <algorithm>
unsigned in() {
unsigned x = 0; char c = getchar();
while (c < '0' || c > '9')
c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 5e5 + 5;

unsigned n, a[N], res[N];

int main() {
//freopen("in", "r", stdin);
freopen("point.in", "r", stdin);
freopen("point.out", "w", stdout);
n = in();
for (unsigned i = 1; i <= n; ++i)
a[i] = in();

unsigned max = 0, num = 0, tmp;
for (unsigned i = 1, l, r; i <= n; i = r + 1) {
l = r = i;
while (r < n && a[r + 1] % a[i] == 0)
++r;
while (l > 1 && a[l - 1] % a[i] == 0)
--l;
tmp = r - l;
if (tmp == max)
res[++num] = l;
if (tmp > max)
max = tmp, res[num = 1] = l;
}

printf("%u %u\n", num, max);
for (unsigned i = 1; i <= num; ++i)
printf("%u ", res[i]);
puts("");
return 0;
}


# T3、演员

$m \ (m \leq 300)$ 个演员排 $n \ (n \leq 10 ^ 6)$ 天班；

## $Source$：

//#pragma GCC optimize(3,"Ofast","inline")
#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
int x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int M = 305, mod = 1e9 + 7;

int n, m, res;
int fac[N], inv[N], f[M + M][M][M];

inline void add(int &_, int __) {
_ += __;
if (_ >= mod)
_ -= mod;
}

int qpow(int base, int b, int ret = 1) {
for (; b; b >>= 1, base = 1ll * base * base % mod)
if (b & 1)
ret = 1ll * ret * base % mod;
return ret;
}

void prep() {
int nn = std::max(n, m);
fac[0] = inv[0] = 1;
for (int i = 1; i <= nn; ++i)
fac[i] = 1ll * fac[i - 1] * i % mod;
inv[nn] = qpow(fac[nn], mod - 2);
for (int i = nn - 1; i; --i)
inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
}

inline int C(const int n, const int m) {
return 1ll * fac[n] * inv[m] % mod * inv[n - m] % mod;
}
inline int A(const int n, const int m) {
return 1ll * fac[n] * inv[n - m] % mod;
}

int main() {
//freopen("in", "r", stdin);
freopen("actor.in", "r", stdin);
freopen("actor.out", "w", stdout);
n = in(), m = in();
prep();
f[0][0][0] = 1;
for (int i = 1; i <= n && i <= m + m; ++i) {
for (int j = 1; j <= m; ++j)
for (int k = j, sum = 0, tmp; k; --k) {
tmp = f[i - 1][j - 1][k - 1]; add(tmp, sum);