Codeforces Round #306 (Div. 2) (构造)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #306 (Div. 2) (构造)相关的知识,希望对你有一定的参考价值。
题意:给一个字符串,求是否含有不重叠的子串"AB"和"BA",长度1e5。
题解:看起来很简单,但是一直错,各种考虑不周全,最后只能很蠢的暴力,把所有的AB和BA的位置求出来,能有一对AB和BA不重叠即可。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 char a[100005]; 5 vector<int> ab; 6 vector<int> ba; 7 int main() 8 { 9 while (~scanf("%s", a)) { 10 int len = strlen(a); 11 ab.clear(); 12 ba.clear(); 13 14 for (int i = 0; i < len - 1; ++i) { 15 if (a[i] == ‘A‘ && a[i + 1] == ‘B‘) { 16 ab.push_back(i); 17 } 18 if (a[i] == ‘B‘ && a[i + 1] == ‘A‘) { 19 ba.push_back(i); 20 } 21 } 22 23 if (ab.size() == 0 || ba.size() == 0) { 24 puts("NO"); 25 } else if (ab.size() > 2 && ba.size() > 2) { 26 puts("YES"); 27 } else { 28 int flag = false; 29 for (int i = 0; i < ab.size(); ++i) { 30 for (int j = 0; j < ba.size(); ++j) { 31 if (!(ab[i] + 1 == ba[j]) && !(ab[i] - 1 == ba[j])) flag = true; 32 } 33 } 34 if (flag) puts("YES"); 35 else puts("NO"); 36 } 37 } 38 return 0; 39 }
题意:输入n, l, r, x,代表有n题,每题有一个难度,选其中部分题(大于2题),要求难度和在[l, r]之间,最大难度最小难度的差不超过x。1 ≤ n ≤ 15
题解:暴力,dfs求全部情况。复杂度2^15
#include <bits/stdc++.h> using namespace std; int a[20]; int n, l, r, x; int vis[20]; int ans; bool ok() { int cnt = 0; for (int i = 0; i < n; ++i) if (vis[i]) cnt++; if (cnt < 2) return false; int low = 1000000000; int high = 1; int sum = 0; for (int i = 0; i < n; ++i) { if (!vis[i]) continue; low = min(low, a[i]); high = max(high, a[i]); sum += a[i]; } if (high - low >= x && sum <= r && sum >= l) return true; return false; } void dfs(int pos) { if (pos == n) { if (ok()) ans++; return ; } vis[pos] = 0; dfs(pos + 1); vis[pos] = 1; dfs(pos + 1); } int main() { while (cin >> n >> l >> r >> x) { for (int i = 0; i < n; ++i) cin >> a[i]; ans = 0; dfs(0); cout << ans << endl; } return 0; }
题意:给一个不超过100位的没有前导零的非负整数,问可不可能移出一部分数字,事剩下至少一位非负整数能被8整除。
题解:能被8整除的数有一个特性:一个整数的末3位若能被8整除,则该数一定能被8整除。求出所有的三位以内能被8整除的数,分别试一下就ok了。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int ans[1000]; 5 char a[105]; 6 //一个整数的末3位若能被8整除,则该数一定能被8整除。 7 bool ok(int x) 8 { 9 int num[10]; 10 int cnt = 0; 11 while (x) { 12 num[cnt++] = x % 10; 13 x /= 10; 14 } 15 reverse(num, num + cnt); 16 int len = strlen(a); 17 int pos = 0; 18 int i; 19 for (i = 0; i < cnt; ++i) { 20 while (a[pos] - ‘0‘ != num[i] && pos < len) { 21 pos++; 22 } 23 if (pos >= len) break;pos++; 24 } 25 if (i == cnt) return true; 26 return false; 27 } 28 29 int main() 30 { 31 int idx = 1; 32 ans[0] = 0; 33 for (int i = 1; i < 200; ++i) { 34 if (i * 8 > 1000) break; 35 ans[idx++] = i * 8; 36 } 37 38 scanf("%s", a); 39 for (int i = 1; i < idx; ++i) { 40 if (ok(ans[i])) { 41 printf("YES\n%d\n", ans[i]); 42 return 0; 43 } 44 } 45 int len = strlen(a); 46 for (int i = 0; i < len; ++i) { 47 if (a[i] == ‘0‘) { 48 printf("YES\n0\n"); 49 return 0; 50 } 51 } 52 printf("NO\n"); 53 54 return 0; 55 }
题意:给一个k(1 ≤ k ≤ 100) ,问是否存在一个无向图至少有一个桥且所有点的度都是k。如果存在给出任意一种解。
题解:对于k+1个点的完全图,所有点的度都是k。考虑两堆k+1的点,然后再用两个点组成桥,每个点和其中一个堆连k-1就可以了。每次桥上的点连堆中两个点,然后删除这两个点的连线,度数不变。同时也可以发现只有k-1为偶数是,即k为奇数时才有解。
1 #include <cstdio> 2 3 using namespace std; 4 5 int main() 6 { 7 int k; 8 while (~scanf("%d", &k)) { 9 if ((k & 1) == 0) { 10 puts("NO"); 11 } else if (k == 1) { 12 puts("YES\n2 1\n1 2"); 13 } else { 14 puts("YES"); 15 printf("%d %d\n", 2 * k + 4, k * k + 2 * k); 16 for (int i = 1; i < k; ++i) { 17 printf("%d %d\n", 2 * k + 3, i); 18 printf("%d %d\n", 2 * k + 4, i + k + 1); 19 } 20 printf("%d %d\n", 2 * k + 3, 2 * k + 4); 21 for (int i = 1; i <= k + 1; ++i) { 22 for (int j = i + 1; j <= k + 1; ++j) { 23 if (i < k - 1 && (i & 1) && i + 1 == j) continue; 24 printf("%d %d\n", i, j); 25 printf("%d %d\n", k + 1 + i, k + 1 + j); 26 } 27 } 28 } 29 } 30 return 0; 31 }
E. Brackets in Implications(构造)
题意:给定01间运算0->0=1 0->1=1 1->0=0 1->1=1 默认从左到右运算 问能不能通过加括号使得表达式值变为0
题解:很容易发现最后一位必须是0,倒数第二位如果是1,那么不用加括号直接为0。如果倒数第二位为0,那么需要在前面找到一个0,两个0即中间的1组成1,然后同上。两个0和中间的1组成1的方法可以为(0(11...110))。
1 #include <iostream> 2 #include <stdio.h> 3 4 using namespace std; 5 6 int a[100005]; 7 int n; 8 int main() 9 { 10 cin >> n; 11 for (int i = 0; i < n; ++i) 12 scanf("%d", a + i); 13 14 if (n == 1) { 15 if (a[0] == 0) puts("YES\n0"); 16 else puts("NO"); 17 } else if (n == 2) { 18 if (a[0] == 1 && a[1] == 0) puts("YES\n1->0"); 19 else puts("NO"); 20 } else if (a[n - 1] == 1) { 21 puts("NO"); 22 } else { 23 if (a[n - 2] == 1) { 24 puts("YES"); 25 for (int i = 0; i < n - 1; ++i) { 26 printf("%d->", a[i]); 27 } 28 puts("0"); 29 } else { 30 int pos = -1; 31 for (int i = n - 3; i >= 0; --i) { 32 if (a[i] == 0) { 33 pos = i; 34 break; 35 } 36 } 37 if (pos == -1) puts("NO"); 38 else { 39 puts("YES"); 40 for (int i = 0; i < pos; ++i) { 41 printf("%d->", a[i]); 42 } 43 printf("(0->("); 44 for (int i = pos + 1; i < n - 2; ++i) { 45 printf("%d->", a[i]); 46 } 47 puts("0))->0"); 48 } 49 } 50 } 51 return 0; 52 }
以上是关于Codeforces Round #306 (Div. 2) (构造)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #306 (Div. 2) 题解
Codeforces Round #306 (Div. 2) A
「日常训练」Two Substrings(Codeforces Round 306 Div.2 A)
「日常训练」Regular Bridge(Codeforces Round 306 Div.2 D)
「日常训练」Divisibility by Eight(Codeforces Round 306 Div.2 C)
「日常训练」Brackets in Implications(Codeforces Round 306 Div.2 E)