zoukankan      html  css  js  c++  java
  • 【LOJ】#2280. 「FJOI2017」矩阵填数

    题解

    我们发现没有限制的小方格可以随便填

    然后考虑有限制的,我们把它切割成一个个小块(枚举相邻的横纵坐标),然后记录一下这个小块的最大值限制(也就是所有覆盖它的矩形最小的最大值)
    记录一下每个小块的大小,和每个小块在哪些有限制的大矩形,且小块的最大值限制等于大矩形的最大值限制,用一个二进制数表示
    然后可以状压dp了,每次枚举这个小块里面填不填最大值,填了就是(V^{n} - (V - 1)^{n})不填就是((V - 1)^{n})

    代码

    #include <bits/stdc++.h>
    #define MAXN 500005
    //#define ivorysi
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define fi first
    #define se second
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {putchar('-');x = -x;}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    const int MOD = 1000000007;
    int T;
    int N,H,W,Q,numx[45],numy[45],cnt,cov[505],cal[505],val[505],tot,ans;
    int f[505][(1 << 10) + 5];
    struct node {
        int x1,x2,y1,y2,val;
    }M[15];
    int inc(int a,int b) {
        a = a + b;
        if(a >= MOD) a -= MOD;
        return a;
    }
    int mul(int a,int b) {
        return 1LL * a * b % MOD;
    }
    int fpow(int x,int c) {
        int res = 1,t = x;
        while(c) {
    	if(c & 1) res = mul(res,t);
    	t = mul(t,t);
    	c >>= 1;
        }
        return res;
    }
    void pre() {
        sort(numx + 1,numx + cnt + 1);
        sort(numy + 1,numy + cnt + 1);
        memset(cov,0,sizeof(cov));
        memset(cal,0,sizeof(cal));
        tot = 0;
        for(int i = 1 ; i <= cnt ; ++i) {
    	for(int j = 1 ; j <= cnt ; ++j) {
    	    int sx = numx[i - 1] + 1,sy = numy[j - 1] + 1;
    	    int tx = numx[i],ty = numy[j];
    	    if(sx > tx || sy > ty) continue;
    	    int v = Q;
    	    bool flag = 0;
    	    for(int k = 1 ; k <= N ; ++k) {
    		if(sx >= M[k].x1 && tx <= M[k].x2 && sy >= M[k].y1 && ty <= M[k].y2) {
    		    v = min(v,M[k].val);
    		    flag = 1;
    		}
    	    }
    	    if(!flag) {
    		ans = mul(ans,fpow(Q,(tx - sx + 1) * (ty - sy + 1)));
    		continue;
    	    }
    	    ++tot;cal[tot] = (tx - sx + 1) * (ty - sy + 1);val[tot] = v;
    	    for(int k = 1 ; k <= N ; ++k) {
    		if(v == M[k].val) {
    		    if(sx >= M[k].x1 && tx <= M[k].x2 && sy >= M[k].y1 && ty <= M[k].y2) {
    			cov[tot] |= 1 << (k - 1);
    		    }
    		}
    	    }
    	}
        }
    }
    void Solve() {
        read(H);read(W);read(Q);read(N);
        cnt = 0;
        ans = 1;
        for(int i = 1 ; i <= N ; ++i) {
    	read(M[i].x1);read(M[i].y1);read(M[i].x2);read(M[i].y2);read(M[i].val);
    	numx[++cnt] = M[i].x1 - 1;numy[cnt] = M[i].y1 - 1;
    	numx[++cnt] = M[i].x2;numy[cnt] = M[i].y2;
        }
        numx[++cnt] = 0;numy[cnt] = 0;
        numx[++cnt] = H;numy[cnt] = W;
        pre();
        memset(f,0,sizeof(f));
        f[0][0] = 1;
        for(int i = 1 ; i <= tot ; ++i) {
    	for(int S = 0 ; S < (1 << N) ; ++S) {
    	    f[i][S | cov[i]] = inc(f[i][S | cov[i]],mul(f[i - 1][S],inc(fpow(val[i],cal[i]),MOD - fpow(val[i] - 1,cal[i]))));
    	    f[i][S] = inc(f[i][S],mul(f[i - 1][S],fpow(val[i] - 1,cal[i])));
    	}
        }
        ans = mul(ans,f[tot][(1 << N) - 1]);
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        read(T);
        while(T--) {
    	Solve();
        }
        return 0;
    }
    
  • 相关阅读:
    python3 初识GUI
    UI自动化测试底层原理
    Oracle导入数据无法导出空表的问题
    Oracle导入大数据量(百万以上)dmp文件,报错ora-12592 :包错误
    selenium 不同版本Driver
    selenium3 调用IE Unable to get browser
    记录错误,服务器上运行自动化脚本找不到窗口。
    python3 实现对代码文件中注释的翻译
    python3 通过邮件发送测试报告
    es6数值类型
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9150710.html
Copyright © 2011-2022 走看看