Codeforces Round 1010 (Div. 2, Unrated)
A. Binary Matrix
题目大意
给你一个01矩阵,如果矩阵的所有行列异或和都是0则是好矩阵,问要让矩阵变好的最小操作次数
解题思路
行的总修改次数和列的总修改次数二者取大即可
代码实现
#include <bits/stdc++.h>using i64 = long long;
const int MOD = 1e9 + 7;int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);int tt;std::cin >> tt;while (tt--) {int n, m;std::cin >> n >> m;std::vector<std::string> g(n);for (int i = 0; i < n; i++) {std::cin >> g[i];}int ans1 = 0, ans2 = 0;for (int i = 0; i < n; i++) {int cnt = 0;for (int j = 0; j < m; j++) {cnt += g[i][j] == '1';}ans1 += cnt % 2;}for (int j = 0; j < m; j++) {int cnt = 0;for (int i = 0; i < n; i++) {cnt += g[i][j] == '1';}ans2 += cnt % 2;}std::cout << std::max(ans1, ans2) << "\n";}
}
B. Floor or Ceil
题目大意
给你一个数x,可以执行n次/2向下取整和m次/2向上取整,问操作完之后可能的最大最小值
解题思路
因为每次操作都会导致变小两倍左右,所以中间穿插向上取整操作是没有意义的,因此只需要把两个操作分开执行完,按照先后顺序就能得到最大最小值
代码实现
#include <bits/stdc++.h>using i64 = long long;int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);int tt;std::cin >> tt;while (tt--) {int x, n, m;std::cin >> x >> n >> m;int x1 = x, n1 = n, m1 = m;while (m1-- && x1 > 1) {x1++;x1 >>= 1;}while (n1-- && x1) {x1 >>= 1;}int x2 = x, n2 = n, m2 = m;while (n2-- && x2) {x2 >>= 1;}while (m2-- && x2 > 1) {x2++;x2 >>= 1;}std::cout << x1 << " " << x2 << "\n";}
}
C. Math Division
题目大意
给你一个数x,等概率随机执行/2向下取整和/2向上取整,问把x变成1的期望是多少,对答案模1e9+7
解题思路
首先去掉最高位,最高位一定是1,并且可以贡献基础操作次数n-1。接着考虑x的奇偶性,当x是偶数的时候,向上向下是等价的,直接/2即可,当二进制数是奇数的时候最低位的1会导致额外的期望次数,可以通过累加每一位的影响来计算
代码实现
#include <bits/stdc++.h>using i64 = long long;
const int MOD = 1e9 + 7;
const int inv2 = 5e8 + 4;int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);int tt;std::cin >> tt;while (tt--) {int n;std::cin >> n;std::string s;std::cin >> s;std::reverse(s.begin(), s.end());s.pop_back();i64 ans = 0;for (auto ch : s) {ans = (ans + (ch == '1')) * inv2 % MOD;}std::cout << (ans + n - 1) % MOD << "\n";}
}