Educational Codeforces Round 45 (Rated for Div. 2)

A.Commentary Boxes

水题

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 
 5 int main() {
 6     LL n, m, a, b;
 7     cin >> n >> m >> a >> b;
 8     n %= m;
 9     LL ans = min(b * n, (m - n) * a);
10     cout << ans << endl;
11     return 0;
12 }
Aguin

B.Micro-World

双指针

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 2e5 + 10;
 4 int a[maxn];
 5 
 6 int main() {
 7     int n, k, ans = 0;
 8     scanf("%d %d", &n, &k);
 9     for(int i = 1; i <= n; ++i) scanf("%d", a + i);
10     sort(a + 1, a + 1 + n);
11     int p = 1;
12     for(int i = 1; i <= n; i++) {
13         while(p < i && a[p] < a[i] - k) p++;
14         while(p < i && a[p] < a[i]) p++, ans++;
15     }
16     printf("%d
", n - ans);
17     return 0;
18 }
Aguin

C.Bracket Sequences Concatenation Problem

判下前后缀合法性

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 3e5 + 10;
 4 typedef long long LL;
 5 string str[maxn];
 6 char s[maxn];
 7 
 8 map<int, int> M;
 9 
10 int main() {
11     int n;
12     scanf("%d", &n);
13     for (int i = 1; i <= n; ++i) {
14         scanf("%s", s + 1);
15         str[i] = string(s + 1);
16         int l = strlen(s + 1), sum = 0, ok = 1;
17         for (int j = l; j >= 1; --j) {
18             if (s[j] == ')') sum++;
19             else sum--;
20             if(sum < 0) ok = 0;
21         }
22         if(ok) M[sum]++;
23     }
24     LL ans = 0;
25     for (int i = 1; i <= n; ++i) {
26         int l = str[i].length(), sum = 0, ok = 1;
27         for (int j = 0; j < l; ++j) {
28             if (str[i][j] == '(') sum++;
29             else sum--;
30             if(sum < 0) ok = 0;
31         }
32         if(ok && M.find(sum) != M.end()) ans += M[sum];
33     }
34     cout << ans << endl;
35     return 0;
36 }
Aguin

D.Graph And Its Complement

如果一个图有多个连通块,记一个连通块中的顶点集S1,S2=V-S1

补图中S1中所有点与S2中所有点都互相连接,故补图只有一个连通块

一个连通块可以连一条链构造 多个连通块可以用孤立点和菊花图 再特判几个点

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int G[1111][1111];
 4 
 5 int main() {
 6     int n, a, b;
 7     scanf("%d %d %d", &n, &a, &b);
 8     if(a > 1 && b > 1 || n == 2 && a == 1 && b == 1 || n == 3 && a == 1 && b == 1) {
 9         puts("NO");
10         return 0;
11     }
12     puts("YES");
13     if(a == 1 && b == 1) {
14         for(int i = 1; i <= n; ++i){
15             for(int j = 1; j <= n; ++j) {
16                 if(j == i + 1 || j == i - 1) putchar('1');
17                 else putchar('0');
18             }
19             puts("");
20         }
21         return 0;
22     }
23     int one = 1, zero = 0;
24     if(b > 1) swap(a, b), swap(one, zero);
25     for(int i = a + 1; i <= n; ++i) {
26         G[1][i] = G[i][1] = 1;
27     }
28     for(int i = 1; i <= n; ++i){
29         for(int j = 1; j <= n; ++j) {
30             if(i == j) putchar('0');
31             else if(G[i][j]) printf("%d", one);
32             else printf("%d", zero);
33         }
34         puts("");
35     }
36     return 0;
37 }
Aguin

E.Post Lamps

暴力枚举倍数感觉是nlogn的

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const LL INF = 1e18;
 5 const int maxn = 1e6 + 10;
 6 int ban[maxn], L[maxn], a[maxn];
 7 
 8 int main() {
 9     int n, m, k, s;
10     scanf("%d %d %d", &n, &m, &k);
11     for(int i = 1; i <= m; ++i) {
12         scanf("%d", &s);
13         ban[s] = 1;
14     }
15     for(int i = 1; i <= k; ++i) scanf("%d", a + i);
16     L[0] = ban[0] ? -1 : 0;
17     for(int i = 1; i < n; ++i) {
18         if(!ban[i]) L[i] = i;
19         else L[i] = L[i-1];
20     }
21     LL ans = INF;
22     for(int i = 1; i <= k; ++i) {
23         int ok = 1, num = 0;
24         for(int j = 0; j < n; ) {
25             if(!ban[j]) num++, j += i;
26             else {
27                 if(L[j] == -1 || j - L[j] >= i) {ok = 0; break;}
28                 else num++, j += i - (j - L[j]);
29             }
30         }
31         if(ok) ans = min(ans, (LL) num * a[i]);
32     }
33     printf("%I64d
", ans == INF ? -1 : ans);
34     return 0;
35 }
Aguin

F.Flow Control

显然只用树边就可以构造了

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 2e5 + 10;
 4 int a[maxn], u[maxn], v[maxn];
 5 int vis[maxn], ans[maxn];
 6 vector<int> G[maxn];
 7 
 8 int dfs(int x) {
 9     vis[x] = 1;
10     int ret = a[x];
11     for(int i = 0; i < G[x].size(); ++i) {
12         int to, d;
13         if(u[G[x][i]] == x) to = v[G[x][i]], d = 1;
14         else to = u[G[x][i]], d = -1;
15         if(vis[to]) continue;
16         int flow = dfs(to);
17         ans[G[x][i]] = d * flow;
18         ret += flow;
19     }
20     return ret;
21 }
22 
23 int main() {
24     int n, m;
25     scanf("%d", &n);
26     for(int i = 1; i <= n; ++i) scanf("%d", a + i);
27     scanf("%d", &m);
28     for(int i = 1; i <= m; ++i) {
29         scanf("%d %d", u + i, v + i);
30         G[u[i]].push_back(i);
31         G[v[i]].push_back(i);
32     }
33     int ok = 1;
34     for(int i = 1; i <= n; ++i) {
35         if(vis[i]) continue;
36         if(dfs(i)) ok = 0;
37     }
38     if(!ok) puts("Impossible");
39     else {
40         puts("Possible");
41         for(int i = 1; i <= m; ++i) printf("%d
", ans[i]);
42     }
43     return 0;
44 }
Aguin

G.GCD Counting

考虑求能被每个因子i整除的路径数再容斥出原问题的答案

枚举每个因子i,只连接两端都能被i整除的边,并用并查集维护连通块大小,可以计算一个块内路径为$frac{(sz - 1) imes sz }{ 2}+ sz$

因为每个数只有根号个因子,所以这样是1.5次的

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 2e5 + 10;
 4 typedef long long LL;
 5 int a[maxn], cnt[maxn];
 6 LL ans[maxn];
 7 
 8 typedef pair<int, int> pii;
 9 vector<pii> G[maxn];
10 
11 int fa[maxn], r[maxn];
12 int Find(int x) {
13     return fa[x] == x ? x : fa[x] = Find(fa[x]);
14 }
15 vector<int> v;
16 void Union(int x, int y) {
17     x = Find(x), y = Find(y);
18     if(x == y) return;
19     fa[x] = y, r[y] += r[x];
20     v.push_back(x);
21     v.push_back(y);
22 }
23 void cln() {
24     for(int i = 0; i < v.size(); ++i) fa[v[i]] = v[i], r[v[i]] = 1;
25     v.clear();
26 }
27 
28 int main() {
29     int n;
30     scanf("%d", &n);
31     for(int i = 1; i <= n; ++i) scanf("%d", a + i), cnt[a[i]]++, fa[i] = i, r[i] = 1;
32     for(int i = 1; i < n; ++i) {
33         int u, v;
34         scanf("%d %d", &u, &v);
35         G[__gcd(a[u], a[v])].push_back(pii(u, v));
36     }
37     for(int i = 1; i < maxn; ++i) {
38         LL tmp = 0;
39         for(int j = i; j < maxn; j += i) {
40             tmp += cnt[j];
41             for(int k = 0; k < G[j].size(); ++k) {
42                 int u = Find(G[j][k].first), v = Find(G[j][k].second);
43                 if(u == v) continue;
44                 tmp -= (LL) r[u] * (r[u] - 1) / 2 + r[u];
45                 tmp -= (LL) r[v] * (r[v] - 1) / 2 + r[v];
46                 Union(u, v), u = Find(u);
47                 tmp += (LL) r[u] * (r[u] - 1) / 2 + r[u];
48             }
49         }
50         ans[i] = tmp, cln();
51     }
52     for(int i = maxn - 1; i >= 1; --i)
53         for(int j = i + i; j < maxn; j += i)
54             ans[i] -= ans[j];
55     for(int i = 1; i < maxn; ++i) if(ans[i]) printf("%d %I64d
", i, ans[i]);
56     return 0;
57 }
Aguin
原文地址:https://www.cnblogs.com/Aguin/p/9173992.html