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;
}
posted @ 2021-09-25 21:58  lahlah  阅读(43)  评论(0编辑  收藏  举报