矩阵矩阵矩(牛客)


求最大子矩阵乘积最大
特别的要么为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];
}
posted @ 2022-01-19 19:55  wzx_believer  阅读(80)  评论(0编辑  收藏  举报