这几天准备期末考试刷题日记断了几天,今天开始重操旧业啦~
写两个水题找找自信~
<Atcoder Beginner 101 - C>
题意:
有一个长度为 n 的序列,这个序列是数 1 ~ n 的乱序,给定一个 k,表示,你可以在这个序列里,选取连续的 k 个数,将他们替换成这 k 个数里最小的那个,问,最少经过多少步,让这个序列所有元素都有变为1。
思路:
枚举就行了,毕竟 Beginner 的 C 题,没什么难度,先找到1的位置,因为选的第一个长度为k的串,一定要包含1,这样这个长度为k的串就都替换成1了,再将这个串的左右端点,推进到整个序列的左右端点即可。那就枚举 1 在选取的第一个长度为k的串的位置即可。写一个O(k)复杂度的循环,具体操作如下:
for(int i = 0; i <= k; i++) {
ans = 1;
int p1 = pos - i, p2 = pos + k - i; //选取的第一个串的左右端点
//向左推进
if((p1 - 1) % k) {
if(p1 > 1) ans += (p1 - 1) / k + 1;
}
else {
if(p1 > 1) ans += (p1 - 1) / k;
}
//向右推进
if((n - p2) % k) {
if(p2 < n) ans += (n - p2) / k + 1;
}
else {
if(p2 < n) ans += (n - p2) / k;
}
minT = min(ans, minT);
}
本人AC代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int Inf = 1e9 + 7;
int n, k, a;
int main() {
cin >> n >> k;
k--;
int pos, ans;
for(int i = 1; i <= n; i++) {
cin >> a;
if(a == 1) pos = i;
}
int minT = Inf;
for(int i = 0; i <= k; i++) {
ans = 1;
int p1 = pos - i, p2 = pos + k - i;
if((p1 - 1) % k) {
if(p1 > 1) ans += (p1 - 1) / k + 1;
}
else {
if(p1 > 1) ans += (p1 - 1) / k;
}
if((n - p2) % k) {
if(p2 < n) ans += (n - p2) / k + 1;
}
else {
if(p2 < n) ans += (n - p2) / k;
}
//cout << ans << endl;
minT = min(ans, minT);
}
cout << minT << endl;
}
<Codeforces 554B>
题意:
有一个 n * n 的布尔矩阵,你可以挑选其中的某些列,把0变1,把1变0,问,执行若干次上述操作,最多能找到多少个只有1的行。
思路:
看着比较动态,仔细想下,是不是,所求的,就是,最大的,相同的行的个数?
因为,每行就三种模式,全0,全1,01混合。
全1时,不用更新列;全0时,更新所有列,01混合时,更新0的列。
所以我只需要找到若干个模式相同的串,再用max维护相同串个数的最大值即可。
因为模式相同的串,就是长的一样的串,更新某些列以后,他们的变化是相同的,
所以是不是,只需要找长得一样的,最多的那个串,的个数,就可以啦~
本人AC代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 107;
int n;
string s[maxn];
int ans;
int main() {
int maxT = 0;
cin >> n;
for(int i = 1; i <= n; i++) cin >> s[i];
for(int i = 1; i <= n; i++) {
ans = 0;
for(int j = 1; j <= n; j++) {
if(s[i] == s[j]) ans++;
}
maxT = max(ans, maxT);
}
cout << maxT << endl;
}