Codeforces Round #786(Div.3)- 1674
Codeforces Round #786 (Div.3) - 1674
赛时:4题,4分,罚时140分钟,1286-->1318,Rank2303。
A. Number Transformation(2s / 512MB)
题面:https://codeforces.com/contest/1674/problem/A
题解:如果 \(y\bmod x > 0\),就肯定无解,如果 \(x > y\),也是无解的,否则答案就是 \(\displaystyle a=1,b=\frac{y}{x}\)。
#include <bits/stdc++.h>
using namespace std;
signed main () {
int t, x, y;
cin >> t;
while (t --) {
cin >> x >> y;
if (x > y || y % x != 0) cout << "0 0\n";
else cout << "1 " << y / x << endl;
}
}
B. Dictionary(2s / 512MB)
题面:https://codeforces.com/contest/1674/problem/B
题解:直接预处理索引,然后查询即可。
#include <bits/stdc++.h>
using namespace std;
map < string, int > mp;
signed main () {
mp.clear ();
int cnt = 0;
for (char a = 'a';a <= 'z'; ++ a) {
for (char b = 'a';b <= 'z'; ++ b) {
if (a == b) continue;
else {
cnt ++;
string s = "";
s += a; s += b;
mp[s] = cnt;
}
}
}
int t; cin >> t;
while (t --) {
string s; cin >> s;
cout << mp[s] << endl;
}
return 0;
}
C. Infinite Replacement(2s / 256MB)
题面:https://codeforces.com/contest/1674/problem/C
题解:如果 \(t\) 为 a,答案就是 1,如果 \(t\) 不是 a 并且 \(t\) 中含有 a,就认定答案有无穷多个,输出 -1,否则答案就是 \(2^{|s|}\),懂一点数学的就知道是乘法原理。
#include <bits/stdc++.h>
using namespace std;
#define int unsigned long long
int t;
string S, T;
inline int ags (string s) {
int res = 0;
for (int i = 0;i < s.size (); ++ i) {
if (s[i] == 'a') res ++;
}
return res;
}
signed main () {
cin >> t;
while (t --) {
cin >> S;
cin >> T;
if (ags (T) > 0 && T.size () > 1) cout << "-1\n";
else {
if (ags (T) > 0) {
cout << "1\n";
}
else {
int n = S.size (), ans = 1;
for (int i = 1;i <= n; ++ i) ans *= 2;
cout << ans << endl;
}
}
}
}
D. A-B-C Sort(2s / 256MB)
题面:https://codeforces.com/contest/1674/problem/D
题解:
如果 \(n\) 是偶数,就判定是否可以通过交换 \(a_{2i-1}\) 和 \(a_{2i}\) 实现排序。
如果 \(n\) 是奇数,就判定是否可以通过交换 \(a_{2i}\) 和 \(a_{2i+1}\) 来实现排序。
#include <bits/stdc++.h>
using namespace std;
int t, n, a[200005], mn;
signed main () {
cin >> t;
while (t --) {
cin >> n;
int ans = 1;
for (int i = 1;i <= n; ++ i) {
cin >> a[i];
}
if (n % 2 == 0) {
for (int i = 1;i <= n; ++ i) {
if (i % 2 == 1) {
if (a[i] > a[i + 1]) swap (a[i], a[i + 1]);
}
}
for (int i = 1;i < n; ++ i) {
if (a[i] > a[i + 1]) ans = 0;
}
}
else {
mn = 1e8;
for (int i = 1;i <= n; ++ i) {
mn = min (mn, a[i]);
}
if (a[1] != mn) ans = 0;
else {
for (int i = 2;i <= n; ++ i) a[i - 1] = a[i];
n --;
for (int i = 1;i <= n; ++ i) {
if (i % 2 == 1) {
if (a[i] > a[i + 1]) swap (a[i], a[i + 1]);
}
}
for (int i = 1;i < n; ++ i) {
if (a[i] > a[i + 1]) ans = 0;
}
}
}
if (ans == 1) cout << "YES\n";
else cout << "NO\n";
}
}
E. Breaking the Wall(2s / 256MB)
题面:https://codeforces.com/contest/1674/problem/E
题解:
第一种方法:打的两部分不相邻,\(f(i,j)=\left\lfloor\frac{a_i+1}{2}\right\rfloor+\left\lfloor\frac{a_j+1}{2}\right\rfloor.\)
第二种方法:打 \(i\) 和 \(i+2\),\(g(i,i+2)=\left\lfloor\frac{a_i}{2}\right\rfloor+\left\lfloor\frac{a_{i+2}}{2}\right\rfloor+1.\)
至此为止,你就能过CF的58个测试点了,不过第二天你会发现自己被hack了。
因为还有第三种方法:打 \(i\) 和 \(i+1\),\(p(i,i+1)=\max\left(\left\lfloor\frac{a_i}{2}\right\rfloor,\left\lfloor\frac{a_{i+1}}{2}\right\rfloor,\left\lfloor\frac{a_i+a_{i+1}+2}{3}\right\rfloor\right).\)
答案很显然就是 \(\displaystyle \min\left(\min_{i=1}^{n}\min_{j=i+1}^{n}f(i,j)+\min_{i=1}^{n-2}g(i,i+2),\min_{i=1}^{n-1}p(i,i+1)\right).\)
#include <bits/stdc++.h>
using namespace std;
int testcases, n, a[200005], b[200005];
signed main () {
testcases = 1;
while (testcases --) {
cin >> n;
for (int i = 1;i <= n; ++ i) {
cin >> a[i]; b[i] = a[i] / 2 + a[i] % 2;
}
sort (b + 1, b + 1 + n);
int ans = b[1] + b[2];
for (int i = 1;i < n - 1; ++ i) {
ans = min (ans, a[i] / 2 + a[i + 2] / 2 + 1);
}
for (int i = 1;i < n; ++ i) {
int I = a[i] / 2 + a[i] % 2;
int J = a[i + 1] / 2 + a[i + 1] % 2;
int K = (a[i] + a[i + 1] + 2) / 3;
I = max (I, max (J, K)); ans = min (ans, I);
}
cout << ans << endl;
}
}
F. Desktop Rearrangement(3s / 256MB)
题面:https://codeforces.com/contest/1674/problem/F
题解:
-
我们直接枚举每一列有多少个图标,总共有多少个图标。
-
然后考虑对于所有的图标,有多少个图标不用移动。
-
然后就能得出答案了。
代码:
#include <bits/stdc++.h>
using namespace std;
int n, m, q;
char a[1005][1005];
signed main () {
cin >> n >> m >> q;
int ovo, cnt; ovo = cnt = 0;
vector < int > a (n * m);
for (int i = 0;i < n; ++ i) {
for (int j = 0;j < m; ++ j) {
char c; cin >> c;
if (c == '*') {
if (a[cnt]) ++ ovo;
cnt ++;
a[j * n + i] = 1;
if (j * n + i < cnt) ++ ovo;
}
}
}
while (q --) {
int x, y; cin >> x >> y;
-- x; -- y;
int i = y * n + x;
if (!a[i]) {
if (a[cnt]) {
++ ovo;
}
++ cnt;
a[i] = 1;
if (i < cnt) ++ ovo;
}
else {
if (i < cnt) -- ovo;
a[i] = 0;
-- cnt;
if (a[cnt]) -- ovo;
}
cout << cnt - ovo << endl;
}
return 0;
}
G. Remove Directed Edges(2s / 256MB)
题面:https://codeforces.com/contest/1674/problem/G
题解:因为原图是有向无环图,所以删去之后的图就请该是一条链,那么问题就转化为求最长的链,可以用 dp 求解。
设 \(f_u\) 为从 \(u\) 开始最长的链,我们就不停的 dfs 转移就行。
代码:
#include <bits/stdc++.h>
using namespace std;
int n, m, indeg[200005], outdeg[200005], u, v, f[200005];
vector < int > graph[200005];
inline void dfs (int u) {
if (f[u]) return ;
f[u] = 1; if (outdeg[u] <= 1) return ;
for (int v : graph[u]) {dfs (v); if (indeg[v] >= 2) f[u] = max (f[u], f[v] + 1);}
}
signed main () {
cin >> n >> m;
for (int i = 1;i <= m; ++ i) {
cin >> u >> v;
outdeg[u] ++;
graph[u].push_back (v);
indeg[v] ++;
}
for (int node = 1;node <= n; ++ node) dfs (node);
int ans = f[1];
for (int i = 2;i <= n; ++ i) ans = max (ans, f[i]);
cout << ans << endl; return 0;
}
浙公网安备 33010602011771号