题目大意
有一个 n × m n\times m n×m 的花园, a i , j = 1 a_{i,j}=1 ai,j=1 表示可以种花, a i , j = 0 a_{i,j}=0 ai,j=0 表示不可以种花,请求出有多少种种花的的方案,使得形成 C
或 F
的形状, n , m ≤ 1 0 3 n,m\le 10^3 n,m≤103。
思路分析
观察 C
和 F
,发现 F
可以认为是 C
的左下角加一笔竖画,所以先求 C
。
求形成 C
的方案数
枚举 C
的左上角的点和左下角的点,即枚举第 j j j 列,黄色点在这一列的第 x x x 行,蓝色点在这一列的第 y y y 行,然后计算一下黄色点能往右延伸几格,蓝色点能往右延伸几格,相乘即可。这一步可以用后缀和 r i , j r_{i,j} ri,j 来实现。
for(int i=1;i<=n;i++){
for(int j=m;j>=1;j--){
if(a[i][j]=='1'){
r[i][j]=0;
}else{
r[i][j]=r[i][j+1]+1;
}
}
}
for(int j=1;j<=m;j++){
for(int x=1;x<=n;x++){
for(int y=x+2;y<=n;y++){
if(a[x][j]=='1'){
break;
}
ansc=ansc+(r[x][j]-1)*(r[y][j]-1);
}
}
}
计算时 ( r x , j − 1 ) × ( r y , j − 1 ) (r_{x,j}-1)\times(r_{y,j}-1) (rx,j−1)×(ry,j−1) 不好看,所以预处理后缀和后非 0 0 0 的 r i , j r_{i,j} ri,j 都减去