求最大子矩阵乘积最大
特别的要么为0,要么为2的次方
因为(2的次方)乘积=2的(次方的和),并且有0一定不能选(除非整个图都为0,一定要特判特判!!!)
问题转化为有障碍的最大子矩阵和
用悬线法(上篇有讲解)和二维前缀和处理
一定要特判0!!!
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int mod=998244353;
const int maxn=1005;
ll n,m,ans;
ll mp[maxn][maxn],a[maxn][maxn],l[maxn][maxn],up[maxn][maxn],r[maxn][maxn];
ll fast_mi(ll aa,ll bb);
ll poww(ll x);
ll f(ll aa,ll bb,ll cc,ll dd);
int main(){
ll n,m,x;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
l[i][j]=r[i][j]=j;up[i][j]=1;
cin>>x;
if(x==0)a[i][j]=-1;
else a[i][j]=poww(x);
mp[i][j]=a[i][j];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
a[i][j]+=(a[i-1][j]+a[i][j-1]-a[i-1][j-1]);
for(int j=2;j<=m;j++)
if(mp[i][j]!=-1&&mp[i][j-1]!=-1)
l[i][j]=l[i][j-1];
for(int j=m-1;j>=1;j--)
if(mp[i][j]!=-1&&mp[i][j+1]!=-1)
r[i][j]=r[i][j+1];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(i>1&&mp[i][j]!=-1){
if(mp[i-1][j]!=-1){
r[i][j]=min(r[i][j],r[i-1][j]);
l[i][j]=max(l[i][j],l[i-1][j]);
up[i][j]=up[i-1][j]+1;
}
ll l1=i-up[i][j]+1,r1=l[i][j],l2=i,r2=r[i][j];
ans=max(ans,f(l1,r1,l2,r2));
}
}
cout<<fast_mi(2,ans)<<endl;
return 0;
}
ll fast_mi(ll aa,ll bb){
ll sum=1;
while(bb){
if(bb&1)sum=sum*aa%mod;
bb>>=1;aa=aa*aa%mod;
}
return sum;
}
ll poww(ll x){
ll cnt=0;
while((x&1)==0)cnt++,x>>=1;
return cnt;
}
ll f(ll aa,ll bb,ll cc,ll dd){
return a[cc][dd]+a[aa-1][bb-1]-a[aa-1][dd]-a[cc][bb-1];
}