题目链接: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的更多相关文章

随机推荐

  1. mysql 之 清空表中数据

    清空表的时候注意外键约束 命令版 查询数据库中所有表名select table_name from information_schema.tables where table_schema='DB_n ...

  2. flex学习

            今天看视频学习的时候,发现css有一个 flex 的属性,非常的好用,为了让自己能够熟记,特意来分享一下flex的用法. 首先,采用Flex布局的元素,称为Flex容器(flex co ...

  3. 11.25-11.27 配置防盗链,访问控制(Directory,FilesMatch)

    4月17日任务 11.25 配置防盗链 11.26 访问控制Directory 11.27 访问控制FilesMatch 扩展 几种限制ip的方法 http://ask.apelearn.com/qu ...

  4. tar命令基本、进阶使用指北

    tar命令基本.进阶使用指北 摘要 打包与压缩是我们在计算机系统日常使用中必备的一个工具,就如我们在使用Windows系统,也需要类似WinRAR的压缩软件来将许多数据.文件打包成一个文件,并压缩其占 ...

  5. Nmon 的安装及使用

    一.安装 Nmon 1.下载地址:http://nmon.sourceforge.net/pmwiki.php?n=Site.Download 2.下载对应系统的 nomn 工具(我用 centos6 ...

  6. RF(scalar/list/dict变量)

     一.scalar 变量 ${} 定义 scalar 变量 ${} 还用来取值 1.set variable  设置变量 ${name} Set Variable zhangsan log ${nam ...

  7. muduo网络库源码学习————Exception类

    Exception类是为异常捕获而设计,可以获得异常的信息以及栈的回溯信息 (原来的代码没有demangle成员函数,输出的格式比较难看,加了demangle成员函数,利用demangle成员函数可以 ...

  8. 刷短视频看新闻看小说也能赚钱的几款APP

    一.抖音极速版 发啦! 刷短视频也能赚钱 第1步:下载[抖音极速版] 第2步:填我邀请码[831008243] 第3步:立刻提现最高[38元]红包 二.今日头条极速版 1元现金速撸 下载[今日头条极速 ...

  9. MySQL 基础入门

    MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用 ...

  10. 微信小程序下拉刷新时有部分区域不随着下拉移动

    问题 区域元素使用(position: fixed),小程序页面下拉刷新时,这部分区域不会随页面下拉移动. 如何解决 删除设置的top属性