HZOJ Silhouette
转化一下题意:给出矩阵每行每列的最大值,求满足条件的矩阵个数。
先将A,B按从大到小排序,显然没有什么影响。如果A的最大值不等于B的最大值那么无解否则一定有解。
考虑从大到小枚举A,B中出现的数s,那么可以将这个矩形分成一些不同的矩形或者L形使之互不影响,且位置的值在[0,s]中,且每行每列的最大值均为s,最后用分步乘法计数原理求解。
例:
5
1 2 2 3 5
2 2 3 4 5
由于矩形是特殊的L形于是我们只考虑L形:
设拐点的矩形为a*b,L上部高为c,左部长为d。
考虑容斥,设f[i]为至少有i行的限制不满足条件(每列都要满足条件),
那么$f[i]=C_a^i * ( s^i * ( (s+1)^{a+c-i} - s^{a+c-i} ))^b * (s^i * (s+1)^{a-i} )^d$
$s^i$保证i行不满足限制,$((s+1)^{a+c-i}-s^{a+c-i})$表示剩下的至少一个满足限制条件(为保证列满足),b次方即每列。这样就考虑完了前b列。
那么多出来的d列呢?大致相同。$(s^i*(s+1)^{a-i})^d$可以发现并没有保证列满足,因为L型左部上面一定比这里大,那么已经保证列满足限制,所以这里就随便选了。
$ans=\prod \sum _{i=0}^{a} -1^i*f[i]$
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #define LL long long 6 using namespace std; 7 const int mod=1e9+7; 8 struct Hash_map 9 { 10 int fi[233333],ni[233333],siz; 11 int key[233333],val[233333]; 12 inline int &operator [] (int x) 13 { 14 int k=x%233333;int i=fi[k]; 15 for(;i&&key[i]!=x;i=ni[i]); 16 if(!i)i=++siz,key[i]=x,val[i]=0,ni[i]=fi[k],fi[k]=i; 17 return val[i]; 18 } 19 }ta,tb; 20 LL poww(LL a,LL b); 21 LL jc[100010],inv[100010]; 22 LL CC(LL n,LL m){return jc[n]*inv[m]%mod*inv[n-m]%mod;} 23 int n,A[100010],B[100010],C[200010],cnt; 24 bool cmp(int a,int b){return a>b;} 25 LL f[100010]; 26 signed main() 27 { 28 // freopen("silhouette4.in","r",stdin); 29 30 jc[0]=inv[0]=1;for(int i=1;i<=100000;i++)jc[i]=jc[i-1]*i%mod,inv[i]=poww(jc[i],mod-2); 31 cin>>n; 32 for(int i=1;i<=n;i++)cin>>A[i],C[++cnt]=A[i],ta[A[i]]++; 33 for(int i=1;i<=n;i++)cin>>B[i],C[++cnt]=B[i],tb[B[i]]++; 34 sort(A+1,A+n+1,cmp);sort(B+1,B+n+1,cmp); 35 if(A[1]!=B[1]){puts("0");return 0;} 36 sort(C+1,C+cnt+1,cmp);cnt=unique(C+1,C+cnt+1)-C-1; 37 38 LL ans=1; 39 int la=1,lb=1,na=0,nb=0; 40 for(int i=1;i<=cnt;i++) 41 { 42 int s=C[i]; 43 la=na,lb=nb; 44 while(na<n&&A[na+1]==s)na++; 45 while(nb<n&&B[nb+1]==s)nb++; 46 47 int a=na-la,b=nb-lb,c=la,d=lb; 48 LL tem=0; 49 for(int j=0;j<=a;j++) 50 { 51 f[j]=CC(a,j)*poww( ( poww(s,j) * (poww(s+1,a+c-j)-poww(s,a+c-j)%mod) )%mod ,b)%mod* 52 poww( poww(s,j)*poww(s+1,a-j)%mod ,d)%mod; 53 if(j&1)tem-=f[j];else tem+=f[j]; 54 tem=(tem%mod+mod)%mod; 55 } 56 ans=(ans*tem)%mod; 57 } 58 printf("%lld\n",ans); 59 } 60 LL poww(LL a,LL b) 61 { 62 a%=mod;LL ans=1; 63 while(b) 64 { 65 if(b&1)ans=ans*a%mod; 66 a=a*a%mod;b=b>>1; 67 } 68 return ans; 69 }
波澜前,面不惊。