[CF321D]Ciel and Flipboard

Posted StaroForgin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF321D]Ciel and Flipboard相关的知识,希望对你有一定的参考价值。

Ciel and Flipboard

题解

我们定义 s ( i , j ) s(i,j) s(i,j)表示 a i , j a_{i,j} ai,j最后取值是否是原值的相反数,容易 发现下面的性质:

  • s ( i , j ) ⊗ s ( i + m , j ) ⊗ s ( m , j ) = 0 ( i < m ) s(i,j)\\otimes s(i+m,j)\\otimes s(m,j)=0 (i< m) s(i,j)s(i+m,j)s(m,j)=0(i<m)
  • s ( i , j ) ⊗ s ( i , j + m ) ⊗ s ( i , m ) = 0 ( j < m ) s(i,j)\\otimes s(i,j+m)\\otimes s(i,m)=0 (j< m) s(i,j)s(i,j+m)s(i,m)=0(j<m)

很明显,我们每次进行操作时,是必定覆盖第 m m m列的,我们的长度是超过整个正方形半的,肯定可以覆盖到中点。
如果覆盖了点 ( i , m ) (i,m) (i,m),那就意味着我们在第 i i i肯定覆盖了连续的 m m m个点,而总长度有只有 2 m − 1 2m-1 2m1,所以 ( i , j + m ) (i,j+m) (i,j+m) ( i , j ) (i,j) (i,j)中肯定有且仅有一个被覆盖到。
所以我们肯定会对其中两个量进行操作,所以其异或值一定是 0 0 0的。
同理,列的部分也是一样的。

有了上面的性质,我们可以考虑将原方阵按中轴线分成四块,大概像这样:

其中 1 1 1 2 2 2 3 3 3 4 4 4块都是 n − 1 2 \\frac{n-1}{2} 2n1大小的正方形,对应位置的 s s s是对应相等或相反的,其相等或相反是可以根据轴上的点的奇偶性确定的。
对于一条长度为 n n n的轴,我们只需要枚举前 m m m个点,就可以确定这条轴上所有点的值。
而当一条轴确定后,另一条轴上所有点的值都是独立的。
我们可以枚举先枚举一条轴上前 m m m个点的值,再确定另一条轴上的点取 0 0 0还是取 1 1 1更大。
另一条轴上的点取 0 0 0还是取 1 1 1更大,显然就要根据它们取 0 0 0时所能贡献的最大值和取 1 1 1时所能贡献的最大值比较得出,我们可以分别枚举它的两种取值,看哪个更大。
当我们两条轴的取值确定时,同一个块内不同点之间的取值都是独立的了,而不同块的对应点之间的关系也是确定的,我们只需要枚举一个点去 0 0 0时四点和大还是取 1 1 1时四点和大即可。
将这轴上点对应的一行或一列上的所有点的和求出来,比较大小即可。
但最开始还是要枚举半条轴的,不过时间复杂度看到 n ⩽ 33 n\\leqslant 33 n33式应该就很容易猜出来了。

总时间复杂度 O ( 2 m n 2 ) O\\left(2^{m}n^2\\right) O(2mn2)

源码

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x<<'\\n'
typedef long long LL;
typedef unsigned long long uLL;     
const LL INF=0x3f3f3f3f3f3f3f3f;  
const int mo=998244353;
const int inv2=499122177;
const int jzm=2333;
const int n1=50;
const int zero=10000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<LL,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){putchar('\\n');while(x>9){putchar((x%10)|'0');x/=10;}putchar(x|'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,m;LL ans,a[35][35];
bool rev[35];
void work(){
	LL res=0;res+=(rev[m]?-a[m][m]:a[m][m]);
	for(int i=1;i<m;i++)
		res+=(rev[i]?-a[i][m]:a[i][m]),
		res+=((rev[i]^rev[m])?-a[i+m][m]:a[i+m][m]);
	for(int i=1;i<m;i++){
		LL sum1=a[m][i]+(rev[m]?-a[m][i+m]:a[m][i+m]);
		for(int j=1;j<m;j++)
			if(rev[j]){
				if(rev[m])sum1+=Fabs(a[j][i]-a[j][i+m]+a[j+m][i]+a[j+m][i+m]);
				else sum1+=Fabs(a[j][i]-a[j][i+m]+a[j+m][i]-a[j+m][i+m]);
			}
			else{
				if(rev[m])sum1+=Fabs(a[j][i]+a[j][i+m]+a[j+m][i]-a[j+m][i+m]);
				else sum1+=Fabs(a[j][i]+a[j][i+m]+a[j+m][i]+a[j+m][i+m]);
			}
		LL sum2=-a[m][i]+(rev[m]?a[m][i+m]:-a[m][i+m]);
		for(int j=1;j<m;j++)
			if(rev[j]){
				if(rev[m])sum2+=Fabs(a[j][i]-a[j][i+m]-a[j+m][i]-a[j+m][i+m]);
				else sum2+=Fabs(a[j][i]-a[j][i+m]-a[j+m][i]+a[j+m][i+m]);
			}
			else{
				if(rev[m])sum2+=Fabs(a[j][i]+a[j][i+m]-a[j+m][i]+a[j+m][i+m]);
				else sum2+=Fabs(a[j][i]+a[j][i+m]-a[j+m][i]-a[j+m][i+m]);
			} 
		res+=max(sum1,sum2);
	}
	ans=max(ans,res);
}
void dosaka(int id){
	if(id>m){work();return ;}
	rev[id]=1;dosaka(id+1);rev[id]=0;dosaka(id+1);
}
signed main(){
	read(n);m=(n+1)/2;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			read(a[i][j]);
	dosaka(1);
	printf("%lld\\n",ans);
	return 0;
}

谢谢!!!

以上是关于[CF321D]Ciel and Flipboard的主要内容,如果未能解决你的问题,请参考以下文章

codechef Ciel and Receipt题解

Ciel and Flowers

网络流(费用流)CodeForces 321B:Ciel and Duel

Codeforces 321E Ciel and Gondolas

CodeForces 321 A - Ciel and Robot

CodeForces 321A Ciel and Robot(数学模拟)