TC Srm524 Div 1 T3
解法:首先,有一个很重要的结论:我们将左视图的一些值交换,主视图不变;我们将主视图的一些值交换,左视图不变。因此,我们可以先将主和左视都从小到大排序
1.
2
排序后,我们可以看到若干个L形区域(如图1),每个L形中的格子允许填的最大值相同。我们可以对于每个"L"分开处理,最后将答案乘起来
对于每个"L",我们可以用dp处理,每一个L(如图2)需满足:
1.每个格的值不超过h,
2.前h1行和前enoughsize列都需满足每行/列至少有1个h
我们设dp状态f[i][j]表示填到第i行,前enoughsize列已有j列满足有h的方案,
转移时,我们枚举下一行要新满足多少列,f[i][j]乘的系数为C(enoughsize-j,k)*h^(enoughsize-j-k)(只满足k个,剩下的不能填h)*(h+1)^(cur(当前行长度)-enoughsize+j)
注意如果是前h1行需满足至少有一个h,因些当k=0时我们要减去一个h都没有的方案,即h^cur
即f[i+1][j+k]+=f[i][j]*xs(上述系数)
End.
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> using namespace std; typedef long long ll; class AxonometricProjection{ public: int howManyWays(vector<int> ,vector<int> ); }; int f[101][101]; int U[10011],D[10011],L[10011],R[10011]; int pra[10011],prb[10011],a[10011],b[10011]; int c[101][101]; int ans,n,m,i,j; int mo=1000000009; int mi(int x,int z) { int l; l=1; while(z){ if(z%2==1)l=(ll)l*x%mo; x=(ll)x*x%mo; z/=2; } return l; } int calc(int h1,int h2,int en,int ful,int h) { int i,j,k,ts,cur; memset(f,0,sizeof(f)); f[0][0]=1; for(i=0;i<h2;i++) for(j=0;j<=en;j++)if(f[i][j]){ if(i+1<=h1)cur=ful; else cur=en; for(k=0;k<=en-j;k++){ ts=(ll)c[en-j][k]%mo*mi(h,en-j-k)%mo*mi(h+1,cur-en+j)%mo; if(i+1<=h1&&k==0)ts=((ll)ts-mi(h,cur))%mo; ts=(ts+mo)%mo; ts=(ll)ts*f[i][j]%mo; f[i+1][j+k]=(f[i+1][j+k]+ts)%mo; } } return f[h2][en]; } int AxonometricProjection::howManyWays(vector<int> A,vector<int> B) { n=A.size();m=B.size(); for(i=0;i<n;i++)a[i+1]=A[i]; for(i=0;i<m;i++)b[i+1]=B[i]; c[0][0]=1; for(i=1;i<=50;i++){ c[i][0]=c[i][i]=1; for(j=1;j<i;j++)c[i][j]=(c[i-1][j]+c[i-1][j-1])%mo; } scanf("%d",&n); for(i=1;i<=n;i++)scanf("%d",&a[i]); scanf("%d",&m); for(i=1;i<=m;i++)scanf("%d",&b[i]); sort(a+1,a+1+n); sort(b+1,b+1+m); if(a[n]!=b[m])return 0; else{ for(i=0;i<=10000;i++)U[i]=L[i]=10011; for(i=1;i<=n;i++){ L[a[i]]=min(L[a[i]],i); R[a[i]]=max(R[a[i]],i); } for(i=n;i>=1;i--)pra[a[i]]=i; for(i=10000;i>=0;i--)if(!pra[i])pra[i]=pra[i+1]; for(i=1;i<=m;i++){ U[b[i]]=min(U[b[i]],i); D[b[i]]=max(D[b[i]],i); } for(i=m;i>=1;i--)prb[b[i]]=i; for(i=10000;i>=0;i--)if(!prb[i])prb[i]=prb[i+1]; ans=1; for(i=0;i<=10000;i++)if(R[i]||D[i]){ if(R[i]&&D[i])ans=(ll)ans*calc(R[i]-L[i]+1,n-L[i]+1,D[i]-U[i]+1,m-U[i]+1,i)%mo; if(R[i]&&!D[i])ans=(ll)ans*calc(R[i]-L[i]+1,R[i]-L[i]+1,0,m-prb[i]+1,i)%mo; if(!R[i]&&D[i])ans=(ll)ans*calc(0,n-pra[i]+1,D[i]-U[i]+1,D[i]-U[i]+1,i)%mo; } return ans; } }