• hdu 5471(状压DP or 容斥)


    想了最复杂的思路,用了最纠结的方法,花了最长的时间,蒙了一种规律然后莫名其妙的过了。 

    MD 我也太淼了。

    后面想了下用状压好像还是挺好写的,而且复杂度也不高。推出的这个容斥的规律也没完全想透我就CAO。

    Count the Grid

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 400    Accepted Submission(s): 86


    Problem Description
    You get a grid of h rows and w columns. Rows are numbered 1, 2, 3, ... , h from top to bottom while columns are numbered 1, 2 , 3, ... , w from left to right. Each cell can be represented by a pair of numbers (x, y), which means this cell is located at row x column y.
    You fill the every cell with an integer ranging from 1 to m.
    Then you start to play with the gird. Every time you chose a rectangle whose upper left cell is (x1, y1) and lower right cell is (x2, y2), finally you calculate the maximum value v of this rectangle.
    After you played n times, you left. When you return, you find that the grid is disappeared. You only remember n rectangles and their corresponding maximum value. You are wondering how many different gird can satisfy your memory. Two grids are different if there is a cell filled different integer.
    Give your answer modulo (109+7).
    Your memory may have some mistakes so that no grid satisfies it, in this case just output 0.
     
    Input
    Multiple test cases. In the first line there is an integer T, indicating the number of test cases. For each test case. First line contain 4 integers h, w, m, n. Next are n lines, each line contain 5 integers x1, y1, x2, y2, v.
    (T=55,1h,w,m104,1x1x2h,1y1y2w,1vm,1n10, there are i test cases for n = i)
     
    Output
    For each test case, please output one line. The output format is "Case #x: ans", x is the case number, starting from 1.
     
    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
    Case #1: 28 Case #2: 76475
     
    Source
     
    Recommend
    hujie   |   We have carefully selected several similar problems for you:  5493 5492 5491 5490 5489 
     
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <stdlib.h>
    #include <math.h>
    using namespace std;
    #define MOD 1000000007
    
    int h,w,m,n;
    struct node
    {
        int x1,y1,x2,y2;
        int num;
        int areacnt;
        int area[1010];//记录其中的小区域
    }g[11],tg[11];
    
    struct Rect
    {
        int x1,y1,x2,y2;
    }rect[1010];
    
    bool flag_noans;
    int tmpsaverect[1010];
    int tmprectcnt;
    
    long long savemul[11];
    bool saverectinarea[1010][11];
    bool flagrect[1010];
    bool flagarea[11];
    bool flagg[11];
    int x[22],y[22];
    long long ans;
    long long tmpans;
    long long ansans;
    
    bool cmpgnum(node tl,node tr)
    {
        return tl.num<tr.num;
    }
    
    bool checkareabelong(int rectpoint,int gi)
    {
        if(g[gi].x1<=rect[rectpoint].x1&&g[gi].y1<=rect[rectpoint].y1 && g[gi].x2>=rect[rectpoint].x2&&g[gi].y2>=rect[rectpoint].y2 )
        {
            return 1;
        }
        return 0;
    }
    
    int getrectareanum(int i)
    {
        return (rect[i].y2-rect[i].y1+1)*(rect[i].x2-rect[i].x1+1);
    }
    
    long long quick_pow(int aa,int bb)//a^b
    {
        long long ans_pow=1;
        long long tmp_pow=aa;
        while(bb)
        {
            if(bb&1)
                ans_pow = (ans_pow*tmp_pow)%MOD;
            tmp_pow = (tmp_pow*tmp_pow)%MOD;
            bb>>=1;
        }
        return ans_pow;
    }
    
    long long cnt_bigoneism(int allnum,int bigm)
    {
        return ((quick_pow(bigm,allnum)-quick_pow(bigm-1,allnum))%MOD+MOD)%MOD;
    }
    
    void dfs(int s,int ends,int cnt_nowhave,int tmp_m)
    {
        //明显错了
        if(cnt_nowhave!=0)
        {
            int cnt_inarea=0;
            int cnt_outarea=0;
            for(int i=0;i<tmprectcnt;i++)
            {
                int tmp_flag=0;
                for(int j=0;j<ends;j++)
                {
                    if(flagarea[j]==true)
                    {
                        if( saverectinarea[i][j]==true )
                        {
                            tmp_flag=1;
                            cnt_inarea += getrectareanum( tmpsaverect[i] );
                            break;
                        }
    
                        /*
                        if( tg[j].x1<=rect[tmpsaverect[i]].x1&&tg[j].y1<=rect[tmpsaverect[i]].y1&& tg[j].x2>=rect[tmpsaverect[i]].x2&&tg[j].y2>=rect[tmpsaverect[i]].y2 )
                        {
                            tmp_flag=1;
                            cnt_inarea += getrectareanum( tmpsaverect[i] );
                            break;
                        }
                        */
                    }
                }
                if(tmp_flag==0)
                {
                    cnt_outarea += getrectareanum( tmpsaverect[i] );
                }
    
            }
            if( !(cnt_outarea==0||cnt_inarea==0) )
            {
                long long tmp_sum = ( quick_pow(tmp_m-1,cnt_inarea)*cnt_bigoneism(cnt_outarea,tmp_m) )%MOD;
                ansans = (ansans+savemul[cnt_nowhave]*tmp_sum)%MOD;
            }
        }
        for(int i=s;i<ends;i++)
        {
            flagarea[i]=true;
            dfs(i+1,ends,cnt_nowhave+1,tmp_m);
            flagarea[i]=false;
        }
    }
    
    long long get_numtime(int mxt,int tm)
    {
        //有t个不满足的情况
        memset(flagarea,false,sizeof(flagarea));
        ansans=0;
        dfs(0,mxt,0,tm);
        return ansans;
    }
    
    int main()
    {
        int T;
        int tt=1;
        scanf("%d",&T);
        //设计模式还是很成问题。
        while(T--)
        {
            flag_noans=false;
            scanf("%d%d%d%d",&h,&w,&m,&n);
            for(int i=0;i<n;i++)
            {
                int x1,y1,x2,y2,tmp;
                scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&tmp);
                x[2*i]=x1;
                x[2*i+1]=x2+1;
                y[2*i]=y1;
                y[2*i+1]=y2+1;
    
                g[i].x1=x1;g[i].y1=y1;
                g[i].x2=x2;g[i].y2=y2;
                g[i].num=tmp;
                g[i].areacnt=0;
            }
            x[2*n]=1;
            x[2*n+1]=h+1;
            y[2*n]=1;
            y[2*n+1]=w+1;
            int id=0;//用来标记最小矩形
            sort(x,x+2*(n+1));
            sort(y,y+2*(n+1));
            int prex=1;
            for(int i=0;i<2*(n+1);i++)
            {
                if(x[i]==prex) continue;
                int prey=1;
                for(int j=0;j<2*(n+1);j++)
                {
                    if(y[j]==prey) continue;
                    rect[id].x1=prex;
                    rect[id].y1=prey;
                    rect[id].x2=x[i]-1;
                    rect[id].y2=y[j]-1;
                    prey=y[j];
                    id++;
                }
                prex=x[i];
            }
    
            for(int i=0;i<id;i++)
            {
                for(int j=0;j<n;j++)
                {
                    if( checkareabelong(i,j) == true )
                    {
                        g[j].area[ g[j].areacnt ]=i;
                        g[j].areacnt++;
                    }
                }
            }
    
            //然后就是容斥原理了
    
            int cntother=0;//统计有多少个格子是完全没有拘束的
            for(int i=0;i<id;i++)
            {
                bool signareain=0;
                for(int j=0;j<n;j++)
                {
                    if( checkareabelong(i,j)==true )
                    {
                        signareain=true;
                        break;
                    }
                }
                if(signareain == false)
                {
                    cntother += getrectareanum(i);
                }
            }
            ans=quick_pow(m,cntother);
            sort(g,g+n,cmpgnum);
            memset(flagrect,false,sizeof(flagrect));
            for(int i=0;i<n;i++)
            {
                int ti;
                for(ti=i;ti<n;ti++)
                {
                    if( g[ti].num != g[i].num ) break;
                    tg[ti-i]=g[ti];
                }
                int cntcnt=0;//用来判断不满足条件的情况
                memset(flagg,0,sizeof(flagg));
                ti--;
                //[i,ti] have the same .num
                tmprectcnt=0;
                int tmpcntnum=0;
                for(int j=0;j<id;j++)
                {
                    if( flagrect[j]==true ) continue;//已经计数过的,不需要
                    for(int gi=i;gi<=ti;gi++)
                        if( checkareabelong(j,gi)==true )
                        {
                            flagrect[j]=true;
                            tmpsaverect[tmprectcnt]=j;
                            tmpcntnum += getrectareanum(j);
                            tmprectcnt++;
                            break;
                        }
                    for(int gi=i;gi<=ti;gi++)
                    {
                        if( checkareabelong(j,gi)==true )
                        {
                            if(flagg[gi]==0)
                            {
                                flagg[gi]=1;
                                cntcnt++;
                            }
                        }
                    }
                }
    
                //容斥原理开始
                if(tmprectcnt==0||cntcnt!=ti-i+1)
                {
                    flag_noans=true;
                    break;
                }
    
                for(int j=0;j<tmprectcnt;j++)
                    for(int j1=0;j1<ti-i+1;j1++)
                    {
                        if( tg[j1].x1<=rect[tmpsaverect[j]].x1&&tg[j1].y1<=rect[tmpsaverect[j]].y1&& tg[j1].x2>=rect[tmpsaverect[j]].x2&&tg[j1].y2>=rect[tmpsaverect[j]].y2 )
                        {
                            saverectinarea[j][j1]=true;
                        }
                        else saverectinarea[j][j1]=false;
                    }
    
                tmpans = cnt_bigoneism(tmpcntnum,g[i].num);// 总的个数
                int flag_sign = -1;
                long long num_mul=1;
                for(int j=1;j<=ti-i;j++)
                {
                    savemul[j]=flag_sign*num_mul;
                    //tmpans = tmpans + flag_sign*num_mul*get_numtime(j,ti-i+1,g[i].num);//j个不满足的情况
                    //tmpans = (tmpans%MOD+MOD)%MOD;
                    flag_sign *= -1;
                    //num_mul=(num_mul*(j+1))%MOD;
    
                }
                get_numtime(ti-i+1,g[i].num);
                tmpans = tmpans + ansans;
                ans = (ans*tmpans)%MOD;
                i=ti;//这一步一直忘了
            }
            printf("Case #%d: ",tt++);
            if(flag_noans==true)
                cout<<0<<endl;
            else cout<<(ans%MOD+MOD)%MOD<<endl;
        }
        return 0;
    }
  • 相关阅读:
    解决Oracle 11g 或 ODAC 11.2 多客户端版本的乱码问题
    C#.ToString()格式大全
    太阳的眼泪
    oracle database link 12154 tns 无法识别错误的解决方案
    List<T>泛型的Find 和 Where 用法范例
    chrome 下载工具支持
    解决,启动office2007时总出现“正在配置Microsoft Office Professional Plus 2007”的字样
    macOS M1 下pip install安装.whl报错“is not a supported wheel on this platform.
    Mail.Ru Cup 2018 Round 3 B. Divide Candies (数论)
    202120221 BUCT ACM集训队每周程序设计竞赛(8) 问题D :一月忘干净
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/4852670.html
Copyright © 2020-2023  润新知