HZOJ Silhouette

轉化一下題意:給出矩陣每行每列的最大值,求知足條件的矩陣個數。ios

先將A,B按從大到小排序,顯然沒有什麼影響。若是A的最大值不等於B的最大值那麼無解不然必定有解。ide

考慮從大到小枚舉A,B中出現的數s,那麼能夠將這個矩形分紅一些不一樣的矩形或者L形使之互不影響,且位置的值在[0,s]中,且每行每列的最大值均爲s,最後用分步乘法計數原理求解。spa

例:code

5blog

1 2 2 3 5排序

2 2 3 4 5ci

 

因爲矩形是特殊的L形因而咱們只考慮L形:string

設拐點的矩形爲a*b,L上部高爲c,左部長爲d。it

考慮容斥,設f[i]爲至少有i行的限制不知足條件(每列都要知足條件),io

那麼$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 }
View Code
相關文章
相關標籤/搜索