CF838A
题目链接:http://codeforces.com/contest/838/problem/A
知识点: (void)
题目大意:
给一个 \(n \times m\) 的 01 矩阵,对于矩阵在 \(n \times m\) 这个范围外的可以都视为 0。将矩阵分为多个 \(k \times k\) 的小块 \((k>1, k \in Z)\),但是要变换矩阵上的元素,使每个小块都为 0 或者都为 1。求最少变换多少个元素可以满足要求。
解题思路:
用 vector<int> point[i] 记录第 \(i\) 行的 1 的位置。然后从 2 开始枚举 \(k\) 到 max(n,m),(剪枝:由某一个 \(k\) 得到的答案一定会优于或等于由 \(n \times k (n > 1, n \in Z)\) 得到的答案。因此,我们考虑完 \(k\) 之后,对于 \(2k, 3k...\) 这些就都不用考虑了,也就是说我们只需考虑 \(k\) 是素数的情况),对于每一个 \(k\),先遍历它对应的每一个小方块的左上角的点,然后遍历每个小方块的每一行,用 lower_bound() 找出这一行中位于对应小方块中的 1 的个数,加起来得到小方块中 1 的总数。然后每个小方块需要变换的元素数就是 min(\(k^2\) - num_of_one, num_of_one) (注:\(k^2\)-num_of_one = num_of_zero),加起来就是对应这个 \(k\) 对应的总变换数,最终答案就取那个最小值。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f, maxn = ;
int vis[maxn];
char st[maxn][maxn];
vector<int> point[maxn];
int main() {
int n, m;
int num = ;
scanf("%d%d", &n, &m);
for (int i = ; i<n; i++) scanf("%s", st[i]);
for (int i = ; i<n; i++)
for (int j = ; j<m; j++) {
if (st[i][j] == '') {
point[i].push_back(j);
num++; //1的总个数
}
}
int maxk = max(n, m), ans = num;
int temp, fail, tone;
for (int k = ; k <= maxk; k++) {
if (vis[k]) continue;
else {
for (int i = k; i <= maxk; i += k) vis[i] = ;
} temp = , fail = , tone = ;
for (int i = ; i<n; i += k) {
if (tone >= num || fail) break; //如果找出了所有的1,那么就没有必要再继续遍历下去了,其他的都是0
for (int j = ; j<m; j += k) { //定左上角
if (tone >= num || fail) break;
int one = ;
for (int z1 = ; z1<k&&i + z1<n; z1++) {
if (tone >= num || fail) break;
int l = lower_bound(point[i + z1].begin(), point[i + z1].end(), j) - point[i + z1].begin();
int r = lower_bound(point[i + z1].begin(), point[i + z1].end(), j + k) - point[i + z1].begin();
one += r - l;
tone += r - l;
}
temp += min(k*k - one, one);
if (temp >= ans) { //如果发现temp已经大于或等于我们目前已知的最佳答案,那么也没有必要继续下去了
fail = ;
break;
}
}
}
if (temp<ans) ans = temp;
}
printf("%d\n", ans); return ;
}
CF838A的更多相关文章
随机推荐
- CUBA:如何准备上线
"在我电脑上是好的呢!"现在看来,这句话更像是调侃开发人员的一个段子,但是"开发环境与生产环境"之间的矛盾依然存在.作为开发者,你需要记住,你写 ...
- 徐州H
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) #defi ...
- 一款被大厂选用的 Hexo 博客主题
首先这是一篇自吹自擂的文章,主题是由多位非前端程序员共同开发,目前经过一年半的迭代已经到达 v1.8.0 版本,并且获得大量认可,甚至某大厂员工已经选用作为内部博客,因此我决定写这篇文章向更多人安利它 ...
- 【集群实战】Rsync数据同步工具
1. Rsync介绍 1.1 什么是Rsync? Rsync是一款开源的,快速的,多功能的,可实现全量及增量的本地或远程数据同步备份的优秀工具.Rsync软件适用于unix/linux/windows ...
- python selenium(用例断言)
1.if ...else ...判断进行断言 from time import * from selenium import webdriver "): driver = webdriver ...
- 初次认识Ngnix
这几天写那个HTTPD,最后觉得学到的好像很少,而且就算最后运行成功了好像也没有什么.所以想学习一些生活中真正在运用着的web服务器, 上网查询了些资料了解到apache, lighttpd, ngi ...
- 最长公共子序列(Longest common subsequence)
问题描述: 给定两个序列 X=<x1, x2, ..., xm>, Y<y1, y2, ..., yn>,求X和Y长度最长的公共子序列.(子序列中的字符不要求连续) 这道题可以 ...
- python数据统计分析
1. 常用函数库 scipy包中的stats模块和statsmodels包是python常用的数据分析工具,scipy.stats以前有一个models子模块,后来被移除了.这个模块被重写并成为了 ...
- 麦基数(p1045)
描述: \(计算2^{P}−1的位数和最后500位数字(用十进制高精度数表示)\) Ⅰ.求位数 \(因为2^p最后一位必定不为0,求2^p-1的位数也就是求2^p位数\) \(2^p的位数确实很难求, ...
- 201771010113 李婷华《面向对象程序设计(Java)》第十二周总结
一.理论知识部分 1.Java的抽象口工具箱( Abstract WindowToolkit, AWT)包含在java.awt包中,它提供了许多用来设计GUI的组件类和容器类. 2.AWT库处理用户界 ...