Codeforces Round #306 (Div. 2) (构造)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #306 (Div. 2) (构造)相关的知识,希望对你有一定的参考价值。

 

A. Two Substrings

题意:给一个字符串,求是否含有不重叠的子串"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 }
View Code

 

B. Preparing Olympiad

题意:输入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;
}
View Code

 

C. Divisibility by Eight

题意:给一个不超过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 }
View Code

 

D. Regular Bridge (构造)

题意:给一个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 }
View Code

 

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 }
View Code

 

以上是关于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)