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
",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 }
View Code
原文地址:https://www.cnblogs.com/Al-Ca/p/11622901.html