1 条题解

  • 0
    @ 2026-10-26 17:31:11

    思路与算法

    先把每个最大值等式拆为所有格≤v且至少一格等于v。容斥枚举哪些矩形缺少等于v的格,把它们的上界降成v-1。按矩形边界压缩坐标;每块的原最低上界cap和提供该上界的约束mask固定,只有被容斥选中的约束与这个mask相交时cap才再降1。聚合同(cap,mask)面积,每个容斥项为各块允许值数的面积次幂之积。

    正确性说明

    坐标块中所有格受到完全相同的上界集合,原最低上界充分决定其取值范围。把某个更大上界降1不会低于已有较小上界,故仅最低约束的选择影响块,判mask相交准确。格子独立选值,相乘计数;容斥恰排除每个等式中没有最大值的违规事件。

    复杂度

    边界≤2n+2,分块及判约束O(n³),块数G=O(n²),2^n容斥各做G次模幂O(Glog(hw)),总O(n³+2^n n²log(hw))时间,空间O(n²)。T≤5逐组处理。

    易错点

    面积必须按原坐标差计算,不能按压缩格数计。上界降为0时正面积块方案0。重复约束和矛盾约束均通过容斥自动处理。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    const long long MOD = 1000000007;
    long long pw(long long a, long long n) {
        long long r = 1;
        while (n) {
            if (n & 1)
                r = r * a % MOD;
            a = a * a % MOD;
            n >>= 1;
        }
        return r;
    }
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int T;
        cin >> T;
        while (T--) {
            int h, w, m, n;
            cin >> h >> w >> m >> n;
            vector<array<int, 5>> q(n);
            vector<int> X = {1, h + 1}, Y = {1, w + 1};
            for (auto &a : q) {
                for (int &x : a)
                    cin >> x;
                X.push_back(a[0]);
                X.push_back(a[2] + 1);
                Y.push_back(a[1]);
                Y.push_back(a[3] + 1);
            }
            sort(X.begin(), X.end());
            X.erase(unique(X.begin(), X.end()), X.end());
            sort(Y.begin(), Y.end());
            Y.erase(unique(Y.begin(), Y.end()), Y.end());
            map<pair<int, int>, long long> groups;
            for (int i = 0; i + 1 < (int)X.size(); i++)
                for (int j = 0; j + 1 < (int)Y.size(); j++) {
                    int cap = m, mask = 0;
                    for (int z = 0; z < n; z++)
                        if (q[z][0] <= X[i] && X[i] <= q[z][2] && q[z][1] <= Y[j] && Y[j] <= q[z][3])
                            cap = min(cap, q[z][4]);
                    for (int z = 0; z < n; z++)
                        if (q[z][4] == cap && q[z][0] <= X[i] && X[i] <= q[z][2] && q[z][1] <= Y[j] &&
                            Y[j] <= q[z][3])
                            mask |= 1 << z;
                    groups[{cap, mask}] += 1LL * (X[i + 1] - X[i]) * (Y[j + 1] - Y[j]);
                }
            long long ans = 0;
            for (int mask = 0; mask < (1 << n); mask++) {
                long long ways = 1;
                for (auto x : groups) {
                    int cap = x.first.first - ((x.first.second & mask) != 0);
                    ways = ways * pw(cap, x.second) % MOD;
                }
                if (__builtin_popcount((unsigned)mask) & 1)
                    ans = (ans - ways + MOD) % MOD;
                else
                    ans = (ans + ways) % MOD;
            }
            cout << ans << '\n';
        }
    }
    
    • 1

    信息

    ID
    1817
    时间
    2000ms
    内存
    512MiB
    难度
    提高
    标签
    递交数
    1
    已通过
    1
    上传者