我,牛子诗宝,代表博王国的荣耀。
FutaRimeWoawaSete · · 题解
sol of CF321D
我们凭感觉如果不是
考虑先从比较暴力地想法入手,设
我们发现在
动笔画画你就可以发现,任意一个子矩形覆盖到了第
反转一下看,列也满足这个性质。所以不管怎么覆盖每次总有两个变量一起变化,于是得到了上面的两条约束。
然后你还发现,子矩阵的操作是线性无关的,这是因为任何一个子矩阵操作不可能被表示成若干个其它子矩阵操作。
再进一步,我们发现对于
后面的其实反而更简单一些,我们考虑先枚举第
然后你发现对于前
所以我们可以得出,在填
当然第
可以发现第
注意到在枚举完前
时间复杂度
#include "bits/stdc++.h"
using namespace std;
const int Len = 36;
#define ll long long
#define int ll
const int Inf = 1e12;
int n,m,c[Len][Len],a[Len][Len];
#define v(x,y) (c[x][y] ? -a[x][y] : a[x][y])
inline int c3(int x,int y,int i)
{
c[x][y] = i , c[x + m][y] = c[x][y] ^ c[m][y];
c[x][y + m] = c[x][y] ^ c[x][m] , c[x + m][y + m] = c[x][y + m] ^ c[m][y + m];
int mx = v(x , y) + v(x + m , y) + v(x , y + m) + v(x + m , y + m);
return mx;
}
inline int c2(int y,int i)
{
c[m][y] = i , c[m][y + m] = c[m][y] ^ c[m][m];
int mx = v(m , y) + v(m , y + m);
for(int i = 1 ; i < m ; i ++) mx += max(c3(i , y , 0) , c3(i , y , 1));
return mx;
}
inline int c1()
{
int mx = 0;
for(int i = 1 ; i <= n ; i ++) mx += v(i , m);
for(int i = 1 ; i < m ; i ++) mx += max(c2(i , 0) , c2(i , 1));
return mx;
}
ll ans = -Inf;
signed main()
{
scanf("%lld",&n);for(int i = 1 ; i <= n ; i ++) for(int j = 1 ; j <= n ; j ++) scanf("%lld",&a[i][j]);
m = (n + 1) / 2;
for(int i = 0 ; i < (1 << m) ; i ++)
{
for(int j = 1 ; j <= m ; j ++) c[j][m] = (i >> (j - 1)) & 1;
for(int j = m + 1 ; j <= n ; j ++) c[j][m] = c[j - m][m] ^ c[m][m];
ans = max(ans , c1());
}
printf("%lld\n",ans);
return 0;
}