「Codeforces 963E」Circles of Waiting 题解

题目

思路

\(f_{i,j}\)\(\left(i,j\right)\) 移动到外面的期望步数

\(f_{i,j}=\begin{cases} 0 & ,i^2+j^2>R^2 \\ p_1f_{i-1,j}+p_2f_{i,j-1}+p_3f_{i+1,j}+p_4f_{i,j+1}+1 & ,i^2+j^2\le R^2 \end{cases}\)

直接消元是 \(\operatorname{O}(R^6)\) 的,不太行

考虑用每行第一个非零数这 \(2R+1\) 个数表达出所有数,从左到右从上到下枚举 \(f_{i+1,j}=\frac{f_{i,j}-p_1f_{i-1,j}-p_2f_{i,j-1}-p_4f_{i,j+1}-1}{p_3}\) 将每一个元的系数都按该式转移,对每行右侧第一个超出范围的有 \(f_{i+1,j}=0\),于是可以得到 \(2R+1\) 个关于这 \(2R+1\) 个主元的方程,直接消元即可

时间复杂度 \(\operatorname{O}(R^3)\)

代码

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
const int N = 120;
const int M = 4005;
const int Mod = 1000000007;

int add(int a, int b) { a += b; if (a >= Mod) { a -= Mod; } return a; }
int sub(int a, int b) { a -= b; if (a < 0) { a += Mod; } return a; }
int pow(int a, int b, int m);
void work(int n);

int k[N][N][N];
int C[N][N];
int equ[N][N];
int lim[N];
int p1, p2, p3, p4;
int R, P;

int main () {
read(R);
P = R + 5;
{
read(p1), read(p2), read(p3), read(p4);
int s = (p1 * 1ll + p2 + p3 + p4) % Mod;
s = pow(s, Mod - 2, Mod);
p1 = p1 * 1ll * s % Mod;
p2 = p2 * 1ll * s % Mod;
p3 = p3 * 1ll * s % Mod;
p4 = p4 * 1ll * s % Mod;
}
for (int i = -R; i <= R; ++i) {
lim[i + P] = int(sqrt(R * R - abs(i) * abs(i)) + 1);
k[P - lim[i + P] + 1][i + P][i + R] = 1;
}
int ip3 = pow(p3, Mod - 2, Mod);
for (int i = -R + 1; i <= R + 1; ++i) {
for (int j = -R; j <= R; ++j) {
if (i > -lim[j + P] + 1 && i <= lim[j + P]) {
for (int l = 0; l <= 2 * R; ++l) {
k[i + P][j + P][l] = sub(k[i - 1 + P][j + P][l], add(
add(p1 * 1ll * k[i - 2 + P][j + P][l] % Mod, p2 * 1ll * k[i - 1 + P][j - 1 + P][l] % Mod),
p4 * 1ll * k[i - 1 + P][j + 1 + P][l] % Mod
)) * 1ll * ip3 % Mod;
}
C[i + P][j + P] = sub(C[i - 1 + P][j + P], add(
add(p1 * 1ll * C[i - 2 + P][j + P] % Mod, p2 * 1ll * C[i - 1 + P][j - 1 + P] % Mod),
add(p4 * 1ll * C[i - 1 + P][j + 1 + P] % Mod, 1)
)) * 1ll * ip3 % Mod;
}
}
}
for (int i = -R; i <= R; ++i) {
for (int l = 0; l <= 2 * R; ++l) {
equ[i + R + 1][l + 1] = k[P + lim[i + P]][i + P][l];
}
equ[i + R + 1][2 * R + 2] = sub(0, C[P + lim[i + P]][i + P]);
}
work(2 * R + 1);
int ans = 0;
for (int l = 0; l <= 2 * R; ++l) {
ans = add(ans, k[P][P][l] * 1ll * equ[l + 1][2 * R + 2] % Mod);
}
ans = add(ans, C[P][P]);
write(ans), EL;
return 0;
}

int pow(int a, int b, int m) {
int ans = 1, now = a;
while (b) {
if (b & 1) {
ans = ans * 1ll * now % m;
}
now = now * 1ll * now % m;
b >>= 1;
}
return ans;
}
void work(int n) {
for (int i = 1; i <= n; ++i) {
int tmp = 0;
for (int j = i; j <= n; ++j) {
if (equ[j][i]) {
tmp = j;
break;
}
}
if (tmp != i) {
for (int j = i; j <= n + 1; ++j) {
std::swap(equ[i][j], equ[tmp][j]);
}
}
int iv = pow(equ[i][i], Mod - 2, Mod);
for (int j = i; j <= n + 1; ++j) {
equ[i][j] = equ[i][j] * 1ll * iv % Mod;
}
for (int j = i + 1; j <= n; ++j) {
for (int k = n + 1; k >= i; --k) {
equ[j][k] = sub(equ[j][k], equ[i][k] * 1ll * equ[j][i] % Mod);
}
}
}
for (int i = n - 1; i >= 1; --i) {
for (int j = i + 1; j <= n; ++j) {
equ[i][n + 1] = sub(equ[i][n + 1], equ[i][j] * 1ll * equ[j][n + 1] % Mod);
}
}
}

「Codeforces 963E」Circles of Waiting 题解
https://blog.seniorious.cc/2020/CF-963E/
作者
Seniorious
发布于
2020年10月13日
许可协议