Codeforces div.4
第一次打div.4难度的题目,也是第一次ak一场……
其他的其实都很简单,不过E的话有点小套路(指自己错了)。
E
思路
如果直接双重循环的话,那么 O ( n 2 ) O(n^2) O(n2)的时间复杂度是无法接受的(也过不了,来自一个看错题目结果直接交了暴力的家伙)。
仔细看题目的话,会看到其实只有26个字符(但是我没看到这一点,所以我就用了map,多了 O ( log n ) O(\log n) O(logn))的时间复杂度的基础,但是题目没有卡这一点,所以还是过了)。
因为是考虑 i < j i<j i<j,因此,可以从末尾枚举到开端,利用容斥原理去思考,就会发现其实答案就是一个字符相同的字符串个数减去两个字符相同的个数。因此,利用容斥就可以在 O ( n ) O(n) O(n)的时间复杂度内解决了(当然这里用了map,时间复杂度还多点)。
还有一种组合数学(?)的角度去考虑,但是容斥反而会比较好懂点。
代码
可行的C++代码。
void solve() {
int n;
cin >> n;
vector<string> c(n);
rep(i, 0, n) {
cin >> c[i];
}
ll ans = 0;
map<char, ll> cnt1, cnt2;
map<char, map<char, ll> > p1, p2;
for (int i = n - 1; i >= 0; -- i) {
char a = c[i][0], b = c[i][1];
cnt1[a] ++; cnt2[b] ++;
p1[a][b] ++; p2[b][a] ++;
ans += cnt1[a] - p1[a][b] + cnt2[b] - p2[b][a];
}
cout << ans << '\n';
}
H
思路
这题比E题简单的其实(E后面的题目都比E简单)。
考虑贪心策略的话,从最高位开始,能异或为1的才异或。因此,这道题直接这样考虑就好了。
代码
可行的c++代码。
void solve() {
int n, k;
cin >> n >> k;
array<int, 31> cnt{0};
rep(_, 0, n) {
int x; cin >> x;
per(i, n - 1; 0) {
if ((x >> i) & 1) {
cnt[i] ++;
}
}
}
per(i, n - 1, 0) {
if (n - cnt[i] <= k) {
k -= n - cnt[i];
cnt[i] = n;
}
}
int ans = 0;
per(i, n - 1, 0) {
if (cnt[i] == n) {
ans += 1 << i;
}
}
cout << ans << '\n';
}