zoukankan      html  css  js  c++  java
  • bzoj 5010: [Fjoi2017]矩阵填数

    Description

    给定一个 h*w 的矩阵,矩阵的行编号从上到下依次为 1..h,列编号从左到右依次1..w。在这个矩阵中你需要在每
    个格子中填入 1..m 中的某个数。给这个矩阵填数的时候有一些限制,给定 n 个该矩阵的子矩阵,以及该子矩阵的
    最大值 v,要求你所填的方案满足该子矩阵的最大值为 v。现在,你的任务是求出有多少种填数的方案满足 n 个限
    制。两种方案是不一样的当且仅当两个方案至少存在一个格子上有不同的数。由于答案可能很大,你只需要输出答
    案 对 1,000,000,007 的取模即可。

    Input

    输入数据的第一行为一个数 T,表示数据组数。
    对于每组数据,第一行为四个数 h,w,m,n。
    接下来 n 行,每一行描述一个子矩阵的最大值 v。每行为五个整
    数 x1,y1,x2,y2,v,表示一个左上角为(x1,y1),右下角为(x2,y2)的子矩阵的最大
    值为 v ( 1≤x1≤x2≤h, 1≤y1≤y2≤w)
    T≤5,1≤h,w,m≤10000,1≤v≤m,1≤n≤10

    Output

    对于每组数据输出一行,表示填数方案 mod 1,000,000,007 后的值。

    Sample Input

    2
    3 3 2 2
    1 1 2 2 2
    2 2 3 3 1
    4 4 4 4
    1 1 2 3 3
    2 3 4 4 2
    2 1 4 3 2
    1 2 3 4 4

    Sample Output

    28
    76475
    ————————————————————————————
    这道题是道比较复杂的容斥 就奇减偶加 QAQ 写起来一堆细节而已QAQ
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long
    using std::sort;
    using std::unique;
    using std::lower_bound;
    const int M=25,mod=1e9+7,N=507;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    int n,m,k,ly,cnt;
    struct pos{int x1,y1,x2,y2,w;}q[M];
    int xs[M],xp,ys[M],yp,vs[M],vp;
    int ans[M][M],mv[M][M],h[M];
    int pmod(LL a,int b){
        LL sum=1;
        while(b){
            if(b&1) sum=sum*a%mod;
            a=a*a%mod; b>>=1;
        }
        return sum;
    }
    void mins(int &x,int y){if(x>y) x=y;}
    int main(){
        int T=read();
        while(T--){
            cnt=0; 
            xp=yp=vp=0;
            n=read(); m=read(); k=read(); ly=read();
            xs[xp++]=1; xs[xp++]=n+1;
            ys[yp++]=1; ys[yp++]=m+1;
            vs[vp++]=k;
            for(int i=0;i<ly;i++){
                q[i].x1=read(); q[i].y1=read();
                q[i].x2=read(); q[i].y2=read();
                q[i].w=read();
                xs[xp++]=q[i].x1; xs[xp++]=q[i].x2+1;
                ys[yp++]=q[i].y1; ys[yp++]=q[i].y2+1;
                vs[vp++]=q[i].w; vs[vp++]=q[i].w-1;
            }    
            sort(xs,xs+xp); xp=unique(xs,xs+xp)-xs-1;
            sort(ys,ys+yp); yp=unique(ys,ys+yp)-ys-1;
            sort(vs,vs+vp); vp=unique(vs,vs+vp)-vs;
            for(int i=0;i<xp;i++) for(int j=0;j<yp;j++) ans[i][j]=(xs[i+1]-xs[i])*(ys[j+1]-ys[j]);
            for(int i=0;i<ly;i++){
                q[i].x1=lower_bound(xs,xs+xp,q[i].x1)-xs;
                q[i].x2=lower_bound(xs,xs+xp,q[i].x2+1)-xs;
                q[i].y1=lower_bound(ys,ys+yp,q[i].y1)-ys;
                q[i].y2=lower_bound(ys,ys+yp,q[i].y2+1)-ys;
                q[i].w=lower_bound(vs,vs+vp,q[i].w)-vs;
            }
            for(int S=0;S<(1<<ly);S++){
                for(int i=0;i<xp;i++) for(int j=0;j<yp;j++) mv[i][j]=vp-1;
                int sum=1;
                for(int k=0;k<ly;k++){
                    int v=q[k].w;
                    if(S>>k&1) sum=-sum,--v;
                    for(int i=q[k].x1;i<q[k].x2;i++)
                    for(int j=q[k].y1;j<q[k].y2;j++) mins(mv[i][j],v);
                }
                for(int i=0;i<vp;i++) h[i]=0;
                for(int i=0;i<xp;i++) for(int j=0;j<yp;j++) h[mv[i][j]]+=ans[i][j];
                for(int i=0;i<vp;i++) sum=(LL)sum*pmod(vs[i],h[i])%mod;
                cnt=(LL)(cnt+sum)%mod;
            }
            printf("%d
    ",(cnt+mod)%mod);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    UIView常用的一些方法小记之setNeedsDisplay和setNeedsLayout
    initWithFrame方法的使用
    加载xib文件,如果想在初始化的时候就添加点东西就重载-(id)initWithCoder:(NSCoder *)aDecoder
    Mac os 下brew的安装与使用—— Homebrew
    Mac os系统gdb调试器的安装与使用
    项目里如何访问AppDelegate
    leetcode 141. Linked List Cycle
    leetcode 206. Reverse Linked List
    从阿里巴巴面试题到java类加载机制
    SpringBoot处理日期转换问题
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7512096.html
Copyright © 2011-2022 走看看