Blog of RuSun

\begin {array}{c} \mathfrak {One Problem Is Difficult} \\\\ \mathfrak {Because You Don't Know} \\\\ \mathfrak {Why It Is Diffucult} \end {array}

CF908D New Year and Arbitrary Arrangement

LuoGu: CF908D New Year and Arbitrary Arrangement

CF: D. New Year and Arbitrary Arrangement

首先要明白题意,一个序列 ab 指 $i$ 位置存在一个 a 并且 $j$ 位置存在一个 b ,满足 i < j 的不同二元组 $(i, j)$ 记为一个答案。可以发现,当前序列如果有 $k$ 个 a ,那么增加一个 b 将会使答案增加 $k$ 。

考虑 DP ,$f _ {i, j}$ 表示当前有 $i$ 个 a ,已经有 $j$ 个答案,满足终止条件后的期望答案。那么有:
$$
f _ {i, j} = \frac {p _ a} {p _ a + p _ b} f _ {i + 1, j} + \frac {p _ b} {p _ a + p _ b} f _ {i, j + i}
$$
考虑边界时,当 $i + j \ge n$ 时,只需要再有一个 b 即可完成,所以每次有 $\frac {p _ a} {p _ a + p _ b}$ 的期望使答案加 $1$ 。

即:
$$
\begin {aligned}
& \sum _ i ^ \infty (\frac {p _ a} {p _ a + p _ b}) ^ i \\
= & - \frac {\frac {p _ a} {p _ a + p _ b}} {\frac {p _ a} {p _ a + p _ b} - 1} \\
= & \frac {p _ a} {p _ b}
\end {aligned}
$$

但是 $f _ {0, 0}$ 转移时会形成环,注意到:
$$
f _ {0, 0} = \frac {p _ a} {p _ a + p _ b} f _ {1, 0} + \frac {p _ b} {p _ a + p _ b} f _ {0, 0}
$$

$$
f _ {1, 0} = f _ {0, 0}
$$
所以用 $f_{1, 0}$ 作为起点。

查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <cstdio>
using namespace std;
typedef long long LL;
template <class Type>
void read(Type &x)
{
char c;
bool flag = false;
while ((c = getchar()) < '0' || c > '9')
c == '-' && (flag = true);
x = c - '0';
while ((c = getchar()) >= '0' && c <= '9')
x = (x << 3) + (x << 1) + c - '0';
flag && (x = ~x + 1);
}
template <class Type>
void write(Type x)
{
x < 0 && (putchar('-'), x = ~x + 1);
x > 9 && (write(x / 10), 0);
putchar(x % 10 + '0');
}
const int N = 1e3 + 10, mod = 1e9 + 7;
int n, pa, pb, invab, invb, f[N][N];
int binpow (int b, int k = mod - 2)
{
int res = 1;
while (k)
{
k & 1 && (res = (LL)res * b % mod);
b = (LL)b * b % mod;
k >>= 1;
}
return res;
}
int dfs (int x, int y)
{
if (x + y >= n)
return (x + y + (LL)pa * invb % mod) % mod;
if (f[x][y])
return f[x][y];
return f[x][y] = ((LL)dfs(x + 1, y) * pa % mod + (LL)dfs(x, y + x) * pb % mod) * invab % mod;
}
int main ()
{
read(n), read(pa), read(pb);
invab = binpow(pa + pb), invb = binpow(pb);
write(dfs(1, 0));
return 0;
}