Codeforces Round #815 (Div. 2)
\(\quad\)早晨去吃饭时,被一个挺漂亮的女生打了招呼,我礼貌地回应你好。返程时,又被一个挺阳光的男生招呼,我也微笑挥手。可笑的是,这两个人,我都认不出是谁……然后就是大学的第一节高数,简单得离谱。虽然我安慰自己毕竟第一节课嘛,水点没事的,可当我翻遍了武大版的高数,深吸一口气,不妙,这也基础过分了吧不是凡尔赛,毕竟以前自学时听信某乎上面的建议看的基本都是纯英文的,还以为国外教材普遍浅显等正式上课会费力的。看来,即使到了大学,数学也还得自学。可不知怎么的忽然想起高二时一个晚上,与一个好友聊了很久。不久他靠信竞保送数学系后,已经三年,如今已是久未联系,也再没这个必要。人与人的差距,觉察时已似身陷泰坦尼克号,于命运的间隙凝视极寒的流川。想起初二躲被窝看\(MIT\)微积分公开课的时光,都忘了是什么时候放下做数学家的梦想了。
\(\qquad\)走走停停,兜兜转转,当寻常的一天成了过去,却是最致命的毒药。
\(\qquad\)把岁月留给岁月吧,好好学习,别管脸皮。
\(\qquad\)在图书馆借了两本难度大点的题集,依我的数学水平,一周不到就可以刷完,可对于今天,也只是平常的一天。
- A
贪心
$code$
/*
a d = b c
if(a d = b c) -> 0
a * d < b * c
b * c / a * d
ans <= 2
*/
# include "bits/stdc++.h"
using namespace std;
int main() {
# ifdef T
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif
int tt;
cin >> tt;
auto gcd = [&](long long a, long long b) -> long long {
while(b ^= a ^= b ^= a %= b);
return a;
};
while(tt--) {
vector<long long> a(5);
for(int i = 1; i <= 4; ++i) cin >> a[i];
long long d1 = gcd(a[1], a[2]), d2 = gcd(a[3], a[4]);
a[1] /= d1, a[2] /= d1;
a[3] /= d2, a[4] /= d2;
long long s1 = a[1] * a[4], s2 = a[2] * a[3];
// cout << "[" << a[1] << " " << a[2] << " " << a[3] << " " << a[4] << "\n";
// cout << "[s1 = " << s1 << " , " << "s2 = " << s2 << "]\n";
if(s1 == s2) {
cout << "0\n";
continue;
}
if(s1 < s2) swap(s1, s2); // make sure s1 >= s2
if((s1 == 0 || s2 == 0) || s1 % s2 == 0) cout << "1\n";
else cout << "2\n";
// cout << ans << "\n";
}
return 0;
}
- B
把最大,次大,最小,次小标记下来,圈中间的两个
$code$
# include "bits/stdc++.h"
using namespace std;
int main() {
# ifdef T
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif
int tt;
cin >> tt;
while(tt--) {
int n;
cin >> n;
int mx_1 = 0, mx_2 = 0, mn_1 = 1e9, mn_2 = 1e9;
for(int i = 1; i <= n; ++i) {
int x;
cin >> x;
if(x >= mx_1) {
mx_2 = mx_1;
mx_1 = x;
}
else if(x > mx_2) {
mx_2 = x;
}
if(x <= mn_1) {
mn_2 = mn_1;
mn_1 = x;
}
else if(x < mn_2) {
mn_2 = x;
}
}
// cout << "[" << mx_1 << ", " << mx_2 << ", " << mn_1 << ", " << mn_2 << "]\n";
cout << mx_1 + mx_2 - mn_1 - mn_2 << "\n";
}
return 0;
}
- C
到后期一\(L\)只切1个,考虑下前期不同情况处理的答案即可
$code$
# include "bits/stdc++.h"
using namespace std;
char str[503];
int main() {
# ifdef T
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif
int tt;
cin >> tt;
while(tt--) {
int n, m;
cin >> n >> m;
// vector<char> str(m + 1);
vector a(n + 1, bitset<503>());
int ans = 0;
for(int i = 1; i <= n; ++i) {
// cin >> (str + 1);
scanf("%s", str + 1);
// cin >> str;
for(int j = 1; j <= m; ++j) {
a[i][j] = str[j] ^ '0';
if(a[i][j] == 1) ++ans;
}
}
// for(int i = 1; i <= n; ++i) {
// for(int j = 1; j <= m; ++j) {
// cout << a[i][j];
// }
// cout << "\n";
// }
// exit(0);
int minn = 4;
for(int i = 1; i < n; ++i) {
for(int j = 1; j < m; ++j) {
int tot = a[i][j] + a[i + 1][j] + a[i + 1][j + 1] + a[i][j + 1];
minn = min(minn, max(1, tot - 1));
}
}
if(ans == 0) {
cout << "0\n";
}
else {
cout << ans - minn + 1 << "\n";
}
}
return 0;
}
- D1
\(DP\)方程显然,优化时想到既然\(n<200\),那数位上就能很大幅度地排除遍历数目
$code$
# include "bits/stdc++.h"
using namespace std;
int main() {
# ifdef T
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif
int tt;
cin >> tt;
while(tt--) {
int n;
cin >> n;
vector<int> a(n);
vector<int> f(n, 1);
for(int i = 0; i < n; ++i) {
cin >> a[i];
}
for(int i = 0; i < n; ++i) {
for(int j = max(i - 255, 0); j < i; ++j) {
if((a[i] ^ j) > (a[j] ^ i)) {
f[i] = max(f[i], f[j] + 1);
}
}
}
cout << *max_element(f.begin(), f.end()) << "\n";
}
return 0;
}
- D2
首先,如果\(a[i] \oplus j = a[j] \oplus i\),那么有\(a[i] \oplus i = a[j] \oplus j\)。
从\(D1\)出发,依然倚靠数位缩减遍历次数,而\(trie\)树可以很好处理数位,对每个新点,每次查询合法的最大值来传递,再上传入\(trie\)
$code$
# include "bits/stdc++.h"
using namespace std;
const int N = 3e5 + 3;
int t[N * 31][2], f[N * 31][2];
# define bit(x,i) ((x) >> (i) & 1)
int main() {
# ifdef T
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif
int tt;
cin >> tt;
while(tt--) {
int n;
cin >> n;
vector<int> a(n);
vector<int> ans(n);
for(int i = 0; i < n; ++i) cin >> a[i];
int trie_index = 0;
for(int i = 0; i < n; ++i) {
int u = 0, mx = 0, x = a[i] ^ i;
for(int j = 30; j >= 0; --j) {
int v = bit(x, j);
if(t[u][v ^ 1]) {
mx = max(mx, f[t[u][v ^ 1]][bit(a[i], j) ^ 1]);
}
if(!t[u][v]) break;
u = t[u][v];
}
ans[i] = mx + 1;
u = 0;
for(int j = 30; j >= 0; --j) {
int v = bit(x, j);
if(!t[u][v]) t[u][v] = ++trie_index;
u = t[u][v];
f[u][bit(i, j)] = max(f[u][bit(i, j)], ans[i]);
}
}
for(int i = 0; i <= trie_index; ++i) t[i][0] = t[i][1] = f[i][0] = f[i][1] = 0;
cout << *max_element(ans.begin(), ans.end()) << "\n";
}
}