[ JLOI 2016 / SHOI 2016 ] 方

题目

Luogu
LOJ
Acwing

思路

001.png
002.png
003.png

代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1000010, M = 2010, S = 1e6 + 7, mod = 1e8 + 7;
int n, m, k;
// Begin Hash
int h[S], ptr[M], idx;
struct NODE { int x, y; } val[M], p[M];
inline bool find(int x, int y) {
    int t = (1ll * x * 101 + y) % S;
    for (int i = h[t]; i != -1; i = ptr[i])
        if (val[i].x == x && val[i].y == y) return true;
    return false;
}
inline void insert(int a, int b) { 
    int x = (1ll * a * 101 + b) % S;
    val[idx] = (NODE) { a, b }, ptr[idx] = h[x], h[x] = idx++;
}
// End Hash
// Begin inv
inline int qmi(int a, int b) {
    int res = 1;
    for (; b; b >>= 1, a = 1ll * a * a % mod)
        if (b & 1) res = 1ll * res * a % mod;
    return res;
}
inline int inv(int x) { return qmi(x, mod - 2); }
// End inv
// Begin calculate
inline int calc_f0() {
    int res = 0;
    for (int i = 1; i <= min(n, m); i++)
        res = (res + 1ll * (n - i + 1) * (m - i + 1) % mod * i % mod) % mod;
    return res;
}
inline int calc(int l, int r, int h) {
    int t = min(l + r, h);
    if (!t) return 0;
    int res = 1ll * t * (t + 3) % mod * inv(2) % mod;
    if (t > l) res -= 1ll * (t - l) * (t - l + 1) % mod * inv(2) % mod;
    if (t > r) res -= 1ll * (t - r) * (t - r + 1) % mod * inv(2) % mod;
    return (res % mod + mod) % mod;
}
inline int calc_f1(NODE t) {
    int a = n - t.x, b = m - t.y, c = t.x, d = t.y;
    int res = (calc(a, c, b) + calc(a, c, d) + calc(b, d, a) + calc(b, d, c)) % mod;
    res -= (min(a, b) + min(b, c) + min(c, d) + min(a, d)) % mod;
    return (res % mod + mod) % mod;
}
NODE rotate(NODE a) { return { a.y, -a.x }; }
NODE operator+(NODE a, NODE b) { return { a.x + b.x, a.y + b.y }; }
NODE operator-(NODE a, NODE b) { return { a.x - b.x, a.y - b.y }; }
NODE operator/(NODE a, int b) { return { a.x / b, a.y / b }; }
inline bool inside(NODE a) { return a.x >= 0 && a.x <= n && a.y >= 0 && a.y <= m; }
inline bool check(NODE a, NODE b) { return inside(a) && inside(b); }
// 如果除以二之后都是整数, 说明在格点上
inline bool on_point(NODE a) { return ((!(a.x & 1)) && (!(a.y & 1))); }
inline int find(NODE x) { return find(x.x, x.y); }
inline int calc_f2(NODE a, NODE b) {
    NODE t = rotate(a - b);
    // a, b 连线作为边长的情况
    int res = check(a + t, b + t) + check(a - t, b - t);
    // a, b 连线作为对角线的情况
    // 真正的另外两个点是 ta / 2, tb / 2
    NODE mid = a + b, ta = mid + t, tb = mid - t;
    if (on_point(ta) && on_point(tb) && check(ta / 2, tb / 2)) res++;
    return res;
}
inline int calc_f3(NODE a, NODE b) {
    NODE t = rotate(a - b);
    int res = 0;
    if (check(a + t, b + t)) res += find(a + t) + find(b + t);
    if (check(a - t, b - t)) res += find(a - t) + find(b - t);
    NODE mid = a + b, ta = mid + t, tb = mid - t;
    if (on_point(ta) && on_point(tb) && check(ta / 2, tb / 2)) 
        res += find(ta / 2) + find(tb / 2);
    return res;
}
inline int calc_f4(NODE a, NODE b) {
    NODE t = rotate(a - b);
    int res = 0;
    if (check(a + t, b + t)) res += (find(a + t) && find(b + t));
    if (check(a - t, b - t)) res += (find(a - t) && find(b - t));
    NODE mid = a + b, ta = mid + t, tb = mid - t;
    if (on_point(ta) && on_point(tb) && check(ta / 2, tb / 2)) 
        res += (find(ta / 2) && find(tb / 2));
    return res;
}
// End calculate
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin >> n >> m >> k;
    memset(h, -1, sizeof h);
    // if (n > m) swap(n, m);
    for (int i = 1; i <= k; i++) 
        cin >> p[i].x >> p[i].y, insert(p[i].x, p[i].y);
    int f0 = calc_f0(), f1 = 0, f2 = 0, f3 = 0, f4 = 0;
    for (int i = 1; i <= k; i++) 
        f1 = (f1 + calc_f1(p[i])) % mod;
    for (int i = 1; i <= k; i++) {
        for (int j = i + 1; j <= k; j++) {
            f2 = (f2 + calc_f2(p[i], p[j])) % mod;
            f3 = (f3 + calc_f3(p[i], p[j])) % mod;
            f4 = (f4 + calc_f4(p[i], p[j])) % mod;
        }
    }
    f3 = 1ll * f3 * inv(3) % mod, f4 = 1ll * f4 * inv(6) % mod;
    int res = ((f0 - f1 + f2 - f3 + f4) % mod + mod) % mod;
    cout << res << endl;
    return 0;
}
posted @ 2021-06-03 16:18  Protein_lzl  阅读(30)  评论(0编辑  收藏  举报