ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[CF321D] Ciel and Flipboard

2021-10-18 19:31:21  阅读:232  来源: 互联网

标签:return Ciel int LL Flipboard putchar CF321D TT 翻转


前言

智商题杀我。

题目

洛谷

CF

讲解

\(n\) 为奇数,操作区间长度 \(m=\frac{n+1}{2}\),显然需要挖掘性质。

假如我们一次操作只会翻转一行,假设翻转第 \(i\) 行的某个长度为 \(m\) 的区间,不难发现 \(a_{i,m}\) 一定会被翻转,如果这一次 \(a_{i,j}(j<m)\) 被翻转,那么 \(a_{i,j+m}\) 一定没有被翻转,vice versa。

更进一步地,一行中如果翻转了偶数次,那么 \(a_{i,j}(j<m)\) 与 \(a_{i,j+m}\) 同号,奇数次则异号。

注意不是对称!某 \(\rm Rain\) 姓同学因为这个和搬题人“精心”构造的大样例 \(\rm \color{red}WA\) 了。

当然列也有相同的性质,只不过中间那个点变成了 \(a_{m,i}\) 。

那么翻转一个 \(m\times m\) 的矩阵意味着什么呢?意味着你可以在满足上述规则的基础上任意变换!因为它们是线性不相关的!

所以只需要枚举一个轴的正负号,另外一个轴贪心求解即可。

时间复杂度 \(O(2^mm^2)\)。

代码

短代码完全不能说明题目难度.jpg
//12252024832524
#include <bits/stdc++.h>
#define TT template<typename T>
using namespace std;

typedef long long LL;
const int MAXN = 35;
const LL INF = 1ll << 60;
int n,m;
LL a[MAXN][MAXN],ans = -INF;

LL Read()
{
	LL x = 0,f = 1; char c = getchar();
	while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();}
	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
	return x * f;
}
TT void Put1(T x)
{
	if(x > 9) Put1(x/10);
	putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
	if(x < 0) putchar('-'),x = -x;
	Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}

int f[MAXN];
void solve()
{
	LL ret = a[m][m]*f[m];
	for(int i = 1;i < m;++ i) ret += f[i] * a[m][i] + f[i] * f[m] * a[m][i+m];//中间那一行 
	for(int i = 1;i < m;++ i)
	{
		LL MAX = -INF;
		for(int sg = -1;sg <= 1;sg += 2)
		{
			LL cur = a[i][m]*sg+a[i+m][m]*sg*f[m];
			for(int j = 1;j < m;++ j) 
				cur += Abs(a[i][j]+a[i+m][j]*f[j]+a[i][j+m]*sg+a[i+m][j+m]*f[j]*f[m]*sg);
			MAX = Max(MAX,cur);
		}
		ret += MAX; 
	}
	ans = Max(ans,ret); 
}
void dfs(int x)
{
	if(x == m+1) {solve();return;}
	f[x] = 1; dfs(x+1); 
	f[x] = -1; dfs(x+1); 
}

int main()
{
//	freopen("taozi.in","r",stdin);
//	freopen("taozi.out","w",stdout);
	n = Read(); m = (n+1) >> 1;
	for(int i = 1;i <= n;++ i)
		for(int j = 1;j <= n;++ j)
			a[i][j] = Read();
	if(n == 1){Put(Abs(a[1][1]),'\n');return 0;}
	dfs(1);
	Put(ans,'\n');
	return 0;
}

标签:return,Ciel,int,LL,Flipboard,putchar,CF321D,TT,翻转
来源: https://www.cnblogs.com/PPLPPL/p/15421963.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有