标签:
想了最复杂的思路,用了最纠结的方法,花了最长的时间,蒙了一种规律然后莫名其妙的过了。
MD 我也太淼了。
后面想了下用状压好像还是挺好写的,而且复杂度也不高。推出的这个容斥的规律也没完全想透我就CAO。
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 400 Accepted Submission(s): 86
#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; }
标签:
原文地址:http://www.cnblogs.com/chenhuan001/p/4852670.html