zoukankan      html  css  js  c++  java
  • JZOJ3206. 【HNOI模拟题】Axonometric Projection

    Description

    让我们来考虑一个单位立方体建成的模型。这个建筑的底是一个n m的单位正方形网格。在每个正方形上面,堆着若干个(可能是0)个单位立方体。每个立方体属于其中一个立方体堆。

    给出了一个建筑的左视图和正视图。请计算有多少种建筑,符合给出的左视图和正视图。答案可能很大,只要返回它除以10^9 + 9的余数即可。

    Input

    第一行是整数n。第二行描述了建筑的左视图。第i个数表示了由上往下看时第i行最高的立方体堆的高度。第三行是整数m。第四行描述了建筑的正视图。第i个数表示了由上往下看时第i列最高的立方体堆的高度。

    Data Constraint

    对于100%的数据,1 <= n,m <= 50,所有出现的数不超过10^4。

    Solution

    • 对于一个左视图或正视图,如果将它的排列顺序调换也没有关系,所以我们可以从小到大排序。
    • 如果我们的两个数组排好了序:
      在这里插入图片描述
    • 将其排成n*m的矩阵,每个位置取最小值,我们发现这个图形变成了很多个L型(或退化的L型)。
    • 针对L型进行DP
    1. 每个L型显然是独立、互不影响的。对于每一个L型设F[i][j]表示做完了i行,其中有j列满足,然后枚举又多出来几列满足,其它的只要满足行至少有一个达到上限,剩下的随便选。
    2. 考虑容斥,枚举至少i行不满足,j列不满足。容斥系数就是
      (-1)(i+j)*dg(i,j) *(d+1)(s-g(i,j)) *C(a,i)*C(b,j)
      d表示这一个L型的限制,s表示总点数,g表示i行j列的总点数,a表示L型行的个数,b表示列的个数。
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 51
    #define ll long long 
    #define mo 1000000009
    using namespace std;
    
    int n,m,i,j,k,x,y,u,v,g,s,d;
    int a[maxn],b[maxn],map[maxn][maxn];
    ll ans,f,sum,jc[maxn],ny[maxn];
    
    int check0(int x,int y,int c){
    	for(int i=y;i<=m;i++) if (map[x][i]!=c) return 0;
    	return 1;
    }
    int check1(int x,int y,int c){
    	for(int i=x;i<=n;i++) if (map[i][y]!=c) return 0;
    	return 1;
    }
    
    ll ksm(ll x,ll y){
    	ll s=1;
    	for(;y;y/=2,x=x*x%mo) if (y&1)
    		s=s*x%mo;
    	return s;
    }
    
    ll C(ll n,ll m){return jc[n]*ny[n-m]%mo*ny[m]%mo;}
    
    int main(){
    	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]){printf("0");return 0;}
    	for(i=1;i<=n;i++) for(j=1;j<=m;j++)
    		map[i][j]=min(a[i],b[j]);
    	jc[0]=ny[0]=1;
    	for(i=1;i<=max(n,m);i++) jc[i]=jc[i-1]*i%mo,ny[i]=ny[i-1]*ksm(i,mo-2)%mo;
    	ans=1;
    	for(x=0,y=0;!(x>=n&&y>=m);x=u,y=v){
    		d=map[x+1][y+1];
    		for(u=x+1;u<=n&&check0(u,y+1,d);u++); u--;
    		for(v=y+1;v<=m&&check1(x+1,v,d);v++); v--;
    		s=(u-x)*(m-y)+(n-x)*(v-y)-(u-x)*(v-y),sum=0;
    		for(i=0;i<=u-x;i++) for(j=0;j<=v-y;j++) {
    			g=i*(m-y)+j*(n-x)-i*j;
    			f=ksm(d,g)*ksm(d+1,s-g)%mo*C(u-x,i)%mo*C(v-y,j)%mo;
    			if ((i+j)&1) sum=(sum-f+mo)%mo; else sum=(sum+f)%mo;
    		}
    		ans=ans*sum%mo;
    	}
    	printf("%lld",ans);
    }
    
  • 相关阅读:
    修改ESMAP中的LOGO
    AppCompatActivity隐藏顶部任务栏
    Android原生开发,view标签导致RecyleView Adapter 中报错的奇葩问题
    用UPUPW做服务器,通过thinkphp5完美搭建APP后台
    hhh
    Redis 学习
    无刷新文件上传
    mongoDB 学习
    MySQL读写分离-架构
    Mysql 通用二进制包安装
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/11700954.html
Copyright © 2011-2022 走看看