CF963E Circles of Waiting
https://www.luogu.com.cn/problem/CF963E
带状矩阵高斯消元板板题
考虑一个带宽,然后正常高斯消元,向下带宽长找主元
向右消元的时候注意要消两倍带宽
没了
看代码吧
code:
#include<bits/stdc++.h>
#define id(x, y) id[x + 51][y + 51]
#define ll long long
#define mod 1000000007
#define N 255
using namespace std;
ll qpow(ll x, ll y) {
ll ret = 1;
for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
return ret;
}
int a[8050][8050], ans[8050];
int n, id[N][N];
void Guass(int n, int band) {
for(int i = 1; i <= n; i ++) {
if(!a[i][i]) {
for(int j = i + 1; j <= min(n, i + band); j ++) if(a[j][i]) {
swap(a[j], a[i]);
break;
}
}
if(!a[i][i]) continue;
ll inv = qpow(a[i][i], mod - 2);
for(int j = i + 1; j <= min(i + band, n); j ++) {
ll t = 1ll * a[j][i] * inv % mod;
for(int k = i; k <= min(n, i + 2 * band); k ++) {
a[j][k] = (a[j][k] - 1ll * a[i][k] * t % mod + mod) % mod;
}
a[j][n + 1] = (a[j][n + 1] - 1ll * a[i][n + 1] * t % mod + mod) % mod;
}
}
for(int i = n; i >= 1; i --) {
ans[i] = a[i][n + 1];
for(int j = i + 1; j <= min(n, i + 2 * band); j ++) {
ans[i] = (ans[i] - 1ll * a[i][j] * ans[j] % mod + mod) % mod;
}
ans[i] = 1ll * ans[i] * qpow(a[i][i], mod - 2) % mod;
}
}
int R, p1, p2, p3, p4;
int main() {
scanf("%d%d%d%d%d", &R, &p1, &p2, &p3, &p4);
int s = qpow(p1 + p2 + p3 + p4, mod - 2);
p1 = 1ll * p1 * s % mod, p2 = 1ll * p2 * s % mod, p3 = 1ll * p3 * s % mod, p4 = 1ll * p4 * s % mod;
for(int x = -R; x <= R; x ++)
for(int y = -R; y <= R; y ++) {
if(x * x + y * y > R * R) continue;
id(x, y) = ++ n;
}
int band = 1;
for(int x = -R; x <= R; x ++)
for(int y = -R; y <= R; y ++) {
if(x * x + y * y > R * R) continue;
a[id(x, y)][id(x, y)] = 1;
a[id(x, y)][n + 1] = 1;
if(id(x - 1, y)) {
a[id(x, y)][id(x - 1, y)] = mod - p1;
band = max(band, abs(id(x - 1, y) - id(x, y)));
}
if(id(x, y - 1)) {
a[id(x, y)][id(x, y - 1)] = mod - p2;
band = max(band, abs(id(x, y - 1) - id(x, y)));
}
if(id(x + 1, y)) {
a[id(x, y)][id(x + 1, y)] = mod - p3;
band = max(band, abs(id(x + 1, y) - id(x, y)));
}
if(id(x, y + 1)) {
a[id(x, y)][id(x, y + 1)] = mod - p4;
band = max(band, abs(id(x, y + 1) - id(x, y)));
}
}
// printf("%d\n", n);
// for(int i = 1; i <= n; i ++) {
// for(int j = 1; j <= n + 1; j ++) printf("%lld ", a[i][j]); printf("\n");
// }printf("\n");
Guass(n, band);
// for(int i = 1; i <= n; i ++) {
// for(int j = 1; j <= n + 1; j ++) printf("%lld ", a[i][j]); printf("\n");
// }
printf("%d", ans[id(0, 0)]);
return 0;
}