Blog of RuSun

OneProblemIsDifficultBecauseYouDontKnowWhyItIsDiffucult

CF908D New Year and Arbitrary Arrangement

LuoGu: CF908D New Year and Arbitrary Arrangement

CF: D. New Year and Arbitrary Arrangement

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

考虑 DPfi,j 表示当前有 ia ,已经有 j 个答案,满足终止条件后的期望答案。那么有:
fi,j=papa+pbfi+1,j+pbpa+pbfi,j+i
考虑边界时,当 i+jn 时,只需要再有一个 b 即可完成,所以每次有 papa+pb 的期望使答案加 1

即:
i(papa+pb)i=papa+pbpapa+pb1=papb

但是 f0,0 转移时会形成环,注意到:
f0,0=papa+pbf1,0+pbpa+pbf0,0

f1,0=f0,0
所以用 f1,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;
}

Gitalk 加载中 ...