Comet OJ Contest # 13 brief explanations

C2

First with disjoint-set maintenance \ (1 \) communication block, and then another set of check and maintenance of (I \) \ row, the first \ (J \) after the first column \ (0 \) of position, that is, if the current location is \ (1 \) then its father was a grid to its right, or is it your own.

Time complexity \ (O (nm \ NQ + log m) \) .

#include<bits/stdc++.h>
#define Rint register int
using namespace std;
const int N = 1003, d[2][4] = {{0, 1, 0, -1}, {1, 0, -1, 0}};
int n, m, q, fa[N][N], cnt, Fa[N * N], Siz[N * N];
char str[N];
bool a[N][N];
inline int getfa(int x, int y){
    return (fa[x][y] == y) ? y : (fa[x][y] = getfa(x, fa[x][y]));
}
inline int Getfa(int x){
    return (Fa[x] == x) ? x : (Fa[x] = Getfa(Fa[x]));
}
inline int id(int x, int y){return (x - 1) * m + y;}
inline void work(int x, int y){
    for(Rint i = 0;i < 4;i ++){
        int nx = x + d[0][i], ny = y + d[1][i];
        if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && a[nx][ny]){
            int fa1 = Getfa(id(x, y)), fa2 = Getfa(id(nx, ny));
            if(fa1 != fa2){
                if(Siz[fa1] > Siz[fa2]) swap(fa1, fa2);
                Fa[fa1] = fa2; Siz[fa2] += Siz[fa1]; -- cnt;
            }
        }
    }
}
int main(){
    scanf("%d%d", &n, &m);
    for(Rint i = 1;i <= n * m;i ++) Fa[i] = i, Siz[i] = 1;
    for(Rint i = 1;i <= n;i ++){
        scanf("%s", str + 1);
        for(Rint j = 1;j <= m;j ++){
            a[i][j] = (str[j] == '1'); fa[i][j] = j + a[i][j]; cnt += a[i][j];
        }
        fa[i][m + 1] = m + 1;
    }
    for(Rint i = 1;i <= n;i ++)
        for(Rint j = 1;j <= m;j ++)
            if(a[i][j]) work(i, j);
    scanf("%d", &q);
    while(q --){
        int x1, y1, x2, y2;
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        for(Rint i = x1;i <= x2;i ++){
            int j = y1;
            while((j = getfa(i, j)) <= y2){
                ++ cnt; a[i][j] = 1; fa[i][j] = j + 1;
                work(i, j);
            }
        }
        printf("%d\n", cnt);
    }
}

D

First of all thrown up a unit root inversion.
\ [F_n = \ frac {1
} {2} ((b + \ sqrt a) ^ n + (b- \ sqrt a) ^ n) \] Then you find \ (P \) is not a prime number, then it is self-closing a.

Then you think of the extension field practice BJ people, is to engage in a domain \ (the Z-[\ sqrt A] = \ {the X-+ the y-\ sqrt A | the X-, the y-\ in the Z-\} \) , and then directly calculate fast power. But you desperate to find, finally there is a \ (\ FRAC {1} {2} \) , and then you scrap it.

Then you see the solution to a problem, find reverse thinking is very important. Usually we are all recursive formula \ (\ rightarrow \) general term formula, but have you thought of general term formula \ (\ rightarrow \) recurrence formula it?

According to the theory of the characteristic equation set \ (F_n AF_ = {} +. 1-n-n-BF_-2} {\) , then \ (x ^ 2-Ax- B = 0 \) is two to \ (b \ pm \ sqrt A \) , so \ (A = B + \ sqrt A + B- \ sqrt A = 2B \) , \ (B = - (B + \ sqrt A) (B- \ sqrt A) = ab & ^ 2 \) . Then quickly obtained by matrix powers \ (F_n \) on it.

#include<bits/stdc++.h>
#define Rint register int
using namespace std;
typedef long long LL;
int T;
LL a, b, p, n;
inline void upd(LL &a, LL b){a += b; if(a >= p) a -= p;}
struct Matrix {
    LL x[2][2];
    inline Matrix(){memset(x, 0, sizeof x);}
    inline Matrix operator = (const Matrix &o){
        memcpy(x, o.x, sizeof x);
        return *this;
    }
    inline Matrix operator * (const Matrix &o) const {
        Matrix res;
        for(Rint i = 0;i < 2;i ++)
            for(Rint k = 0;k < 2;k ++)
                for(Rint j = 0;j < 2;j ++)
                    upd(res.x[i][j], (__int128) x[i][k] * o.x[k][j] % p);
        return res;
    }
} A, B;
inline Matrix kasumi(Matrix A, LL b){
    Matrix res; res.x[0][0] = res.x[1][1] = 1;
    while(b){
        if(b & 1) res = res * A;
        A = A * A; b >>= 1;
    }
    return res;
}
int main(){
    scanf("%d", &T);
    while(T --){
        scanf("%lld%lld%lld%lld", &n, &a, &b, &p); a %= p; b %= p;
        if(n == 0){puts("1"); continue;}
        if(n == 1){printf("%lld\n", b); continue;}
        A.x[0][0] = 2 * b % p; A.x[0][1] = (a + p - (__int128) b * b % p) % p;
        A.x[1][0] = 1; B.x[0][0] = b; B.x[1][0] = 1;
        B = kasumi(A, n - 1) * B;
        printf("%lld\n", B.x[0][0]);
    }
}

E

This is a very scary look of computational geometry.

First, we found that this range is in fact two spaced \ (2D \) portion between the parallel lines, so we enumerate wherein a parallel line, it always found through a point, this point we enumerate \ (A \) , to see what it can cover at a further time point \ (B \) .

Category talk.

  1. \ (DIS (A, B) \ Le 2D \) , provided \ (\ Alpha = \ arctan \ FRAC {y_B-Y_A} {x_b-X_a} \) , the angle range in which linearity is \ ([\ alpha, \ alpha + \ pi] \)

  2. \ (DIS (A, B)> 2D \) , provided \ (\ Beta = \ arcsin \ FRAC {2D} {DIS (A, B)} \) , the angle range in which linearity is \ ([\ alpha, \ alpha + \ beta] \ cup [ \ alpha + \ pi- \ beta, \ alpha + \ pi] \)

If you do not understand the words, they look at a map.

The question then transformed into a pile given range, find a point is covered up many times. This is a classic problem

#include<bits/stdc++.h>
#define Rint register int
using namespace std;
const int N = 16003;
const double PI = acos(-1);
int n, d, x[N], y[N], ans, tag[N], len, tot;
double l[N], r[N], val[N];
inline void add(double x, double y){
    if(x < 0 && y < 0) x += PI * 2, y += PI * 2;
    if(x < 0){
        l[++ tot] = x + 2 * PI; r[tot] = 2 * PI; val[++ len] = x + 2 * PI; val[++ len] = 2 * PI;
        l[++ tot] = 0; r[tot] = y; val[++ len] = 0; val[++ len] = y;
    } else {
        l[++ tot] = x; r[tot] = y; val[++ len] = x; val[++ len] = y;
    }
}
inline void work(int p){
    len = tot = 0;
    for(Rint i = 1;i <= n;i ++) if(i != p){
        double alpha = atan2(y[i] - y[p], x[i] - x[p]), dis = (x[i] - x[p]) * (x[i] - x[p]) + (y[i] - y[p]) * (y[i] - y[p]);
        if(dis <= d * d){
            add(alpha, alpha + PI);
        } else {
            double beta = asin(1.0 * d / sqrt(dis));
            add(alpha, alpha + beta); add(alpha + PI - beta, alpha + PI);
        }
    }
    sort(val + 1, val + len + 1);
    len = unique(val + 1, val + len + 1) - val - 1;
    for(Rint i = 1;i <= tot;i ++){
        int a = lower_bound(val + 1, val + len + 1, l[i]) - val, b = lower_bound(val + 1, val + len + 1, r[i]) - val + 1;
        ++ tag[a]; -- tag[b];
    }
    for(Rint i = 1;i <= len;i ++){
        ans = max(ans, tag[i] += tag[i - 1]); tag[i - 1] = 0;
    } tag[len] = 0;
}
int main(){
    scanf("%d%d", &n, &d); d <<= 1;
    for(Rint i = 1;i <= n;i ++) scanf("%d%d", x + i, y + i);
    for(Rint i = 1;i <= n;i ++) work(i);
    printf("%d", ans + 1);
}

Guess you like

Origin www.cnblogs.com/AThousandMoons/p/11755494.html
Recommended