Codeforces Round #306 (Div. 2)

来源:互联网 发布:卸载手机预装软件 编辑:程序博客网 时间:2024/05/01 07:15

A.给定一个字符串,问是否存在不重叠的两个串”AB”和”BA”,顺序任意.

先从左到右遍历一遍,然后找出最靠左的”AB”的位置和”BA”的位置
然后从右往左遍历一遍,找出最靠右的”BA”的位置和”AB”的位置
然后比较一下就行了

/*************************************************************************    > File Name: A.cpp    > Author: ALex    > Mail: zchao1995@gmail.com     > Created Time: 2015年06月05日 星期五 18时58分41秒 ************************************************************************/#include <functional>#include <algorithm>#include <iostream>#include <fstream>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#include <queue>#include <stack>#include <map>#include <bitset>#include <set>#include <vector>using namespace std;const double pi = acos(-1.0);const int inf = 0x3f3f3f3f;const double eps = 1e-15;typedef long long LL;typedef pair <int, int> PLL;string str;int main() {    while (cin >> str) {        int len = str.length();        int pos11 = -1, pos12 = -1, pos21 = -1, pos22 = -1;        for (int i = 0; i < len - 1; ++i) {            if (pos11 == -1 && str[i] == 'A' && str[i + 1] == 'B') {                pos11 = i;            }            if (pos12 == -1 && str[i] == 'B' && str[i + 1] == 'A') {                pos12 = i;            }        }        for (int i = len - 1; i > 0; --i) {            if (pos21 == -1 && str[i] == 'A' && str[i - 1] == 'B') {                pos21 = i - 1;            }            if (pos22 == -1 && str[i] == 'B' && str[i - 1] == 'A') {                pos22 = i - 1;            }        }        bool flag = 0;        if (pos11 != -1 && pos21 != -1 && pos11 + 1 < pos21) {            flag = 1;        }        if (pos12 != -1 && pos22 != -1 && pos12 + 1 < pos22) {            flag = 1;        }        if (flag) {            cout << "YES" << endl;        }        else {            cout << "NO" << endl;        }    }    return 0;}

B.给定n个问题,以及它们的难度,问合法的方案数
n<=15,所以直接枚举2n就行

/*************************************************************************    > File Name: B.cpp    > Author: ALex    > Mail: zchao1995@gmail.com     > Created Time: 2015年06月05日 星期五 17时55分00秒 ************************************************************************/#include <functional>#include <algorithm>#include <iostream>#include <fstream>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#include <queue>#include <stack>#include <map>#include <bitset>#include <set>#include <vector>using namespace std;const double pi = acos(-1.0);const int inf = 0x3f3f3f3f;const double eps = 1e-15;typedef long long LL;typedef pair <int, int> PLL;int C[20];int main() {    int n, l, r, x;    while (cin >> n >> l >> r >> x) {        for (int i = 0; i < n; ++i) {            cin >> C[i];        }        int ans = 0;        for (int i = 0; i < (1 << n); ++i) {            int sum = 0;            int bits = 0;            int maxs = -1, mins = inf;            for (int j = 0; j < n; ++j) {                if (i & (1 << j)) {                    ++bits;                    sum += C[j];                    maxs = max(maxs, C[j]);                    mins = min(mins, C[j]);                }            }            if (bits >= 2 && sum >= l && sum <= r && maxs - mins >= x) {                ++ans;            }        }        cout << ans << endl;    }    return 0;}

C.给定一个长度不超过100的正整数,然后可以删除一些位置上的数,问是否存在方案,使得最后形成的数对8取模为0,如果存在,输出一组解

我是用dp来做的,似乎麻烦了点
dp[i][j][k] 表示前i位,删除j位,模8为k的可行性
然后记录这个状态的前驱状态,最后把答案迭代出来就行了,注意前导0

/*************************************************************************    > File Name: C.cpp    > Author: ALex    > Mail: zchao1995@gmail.com     > Created Time: 2015年06月05日 星期五 18时03分45秒 ************************************************************************/#include <functional>#include <algorithm>#include <iostream>#include <fstream>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#include <queue>#include <stack>#include <map>#include <bitset>#include <set>#include <vector>using namespace std;const double pi = acos(-1.0);const int inf = 0x3f3f3f3f;const double eps = 1e-15;typedef long long LL;typedef pair <int, int> PLL;string str;bool dp[110][110][10];bool use[110];struct node {    int rest, del;}last[110][110][10];int main() {    while (cin >> str) {        memset(dp, 0, sizeof(dp));        dp[0][0][0] = 1;        last[0][0][0].rest = last[0][0][0].del = -1;        int n = str.length();        for (int i = 0; i < n; ++i) {            for (int j = 0; j <= i; ++j) {                for (int k = 0; k < 8; ++k) {                    if (dp[i][j][k]) {                        dp[i + 1][j + 1][k] = 1;                        dp[i + 1][j][(k * 10 + str[i] - '0') % 8] = 1;                        last[i + 1][j + 1][k].rest = k;                        last[i + 1][j + 1][k].del = j;                        last[i + 1][j][(k * 10 + str[i] - '0') % 8].rest = k;                        last[i + 1][j][(k * 10 + str[i] - '0') % 8].del = j;                    }                }            }        }           bool flag = 0;        int del;        for (int i = 0; i < n; ++i) {            if (dp[n][i][0]) {                flag = 1;                del = i;                break;            }        }        if (!flag) {            cout << "NO" << endl;            continue;        }        cout << "YES" << endl;        for (int i = 0; i <= n; ++i) {            use[i] = 0;        }        int m = n, rest = 0;        while (m > 0) {            node &now = last[m][del][rest];            if (now.del == del) {                use[m] = 1;            }            --m;            rest = now.rest;            del = now.del;        }        string ans ="";        for (int i = 1; i <= n; ++i) {            if (use[i]) {                ans += str[i - 1];            }        }           int len = ans.length();        int s = 0;        while (s != len - 1 && ans[s] == '0') {            ++s;        }        for (int i = s; i < len; ++i) {            cout << ans[i];        }        cout << endl;    }    return 0;}

D.给定k,让你构造一张无向连通图,且图中所有顶点的度为k,图中至少存在一条割边;如果答案不存在,输出NO

显然如果k是偶数一定无解
当k是奇数,由于图中存在割边,割边2侧的图是对称的,
考虑一侧的图,我yy的方法是,令一侧的点个数为2*k-1
设割边两侧的点编号为1, 2*k
先从1出衍生出点(2, 3, …, k)
然后从2出衍生出点(k + 1, k + 2, …, 2 * k - 1)
然后对于编号为(2, 3, …, k)的点,向编号为(k + 1, k + 2, …, 2 * k - 1)的点都连一条边
这个过程之后,编号为(k + 1, k + 2, …, 2 * k - 1)的点的度数就是k-1了
而共有k - 1个这样的点,k-1是偶数
所以只要两两互连就行了
另外一侧的图只要在输出的时候给点的编号加上2*k - 1的偏移量就行了

/*************************************************************************    > File Name: D.cpp    > Author: ALex    > Mail: zchao1995@gmail.com     > Created Time: 2015年06月05日 星期五 20时19分03秒 ************************************************************************/#include <functional>#include <algorithm>#include <iostream>#include <fstream>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#include <queue>#include <stack>#include <map>#include <bitset>#include <set>#include <vector>using namespace std;const double pi = acos(-1.0);const int inf = 0x3f3f3f3f;const double eps = 1e-15;typedef long long LL;typedef pair <int, int> PLL;bool mat[440][440];bool use[440][440];int main() {    int k;    while (~scanf("%d", &k)) {        if (k % 2 == 0) {            printf("NO\n");            continue;        }        memset(mat, 0, sizeof(mat));        for (int i = 2; i <= k; ++i) {            mat[1][i] = 1;            mat[i][1] = 1;        }        for (int i = 2; i <= k; ++i) {            for (int j = k + 1; j <= 2 * k - 1; ++j) {                mat[i][j] = mat[j][i] = 1;            }        }        for (int i = k + 1; i <= 2 * k - 1; i += 2) {            mat[i][i + 1] = 1;            mat[i + 1][i] = 1;        }        int ans = 0;        for (int i = 1; i <= 2 * k - 1; ++i) {            for (int j = 1; j <= 2 * k - 1; ++j) {                ans += mat[i][j];            }        }        ++ans;        printf("YES\n");        printf("%d %d\n", 4 * k - 2, ans);        memset(use, 0, sizeof(use));        for (int i = 1; i <= 2 * k - 1; ++i) {            for (int j = 1; j <= 2 * k - 1; ++j) {                if (mat[i][j] && !use[i][j]) {                    printf("%d %d\n", i, j);                    printf("%d %d\n", i + 2 * k - 1, j + 2 * k - 1);                    use[i][j] = use[j][i] = 1;                }            }        }        printf("%d %d\n", 1, 2 * k);    }}

E.定义运算a>b a,b非零即一,仅当a为1,b为0时,结果为0,其他结果为1,不加括号时,运算顺序是从左到右,给定n个数,问通过这个操作这n个数 的运算结果是否可以为0,如果可以,就输出一种方案,否则输出NO

显然,如果最后一个数是1,一定无解
如果倒数第二个数为1,那么可以直接运算
如果倒数第二个数为0,而它前面是0,那么这2个数先计算,就可以得到1,再之前的数就可以顺序运算
如果倒数第二个数为0,而它前面是1,那么这2个数必须先计算,否则最后结果就是1 0 0 ,无论如何计算结果一定是1
所以我们只要从后往前这样考虑就行了,注意判断一种情况,考虑完所有的数,还是没能得到1,那么应该是NO的,比如1 0 0 这样的序列

/*************************************************************************    > File Name: E.cpp    > Author: ALex    > Mail: zchao1995@gmail.com     > Created Time: 2015年06月05日 星期五 21时12分05秒 ************************************************************************/#include <functional>#include <algorithm>#include <iostream>#include <fstream>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#include <queue>#include <stack>#include <map>#include <bitset>#include <set>#include <vector>using namespace std;const double pi = acos(-1.0);const int inf = 0x3f3f3f3f;const double eps = 1e-15;typedef long long LL;typedef pair <int, int> PLL;static const int N = 100100;int Arr[N];int leftNum[N];int rightNum[N];int main() {    int n;    while (~scanf("%d", &n)) {        for (int i = 1; i <= n; ++i) {            scanf("%d", &Arr[i]);        }        if (Arr[n]) {            printf("NO\n");            continue;        }        if (n == 1) {            printf("%s\n", Arr[n] ? "NO" : "YES");            if (!Arr[n]) {                printf("0\n");            }            continue;        }        if (n == 2) {            if (Arr[1] && !Arr[2]) {                printf("YES\n");                printf("1->0\n");            }            else {                printf("NO\n");            }            continue;        }        memset(leftNum, 0, sizeof(leftNum));        memset(rightNum, 0, sizeof(rightNum));        int last = Arr[n - 1];        int pos = -1;        bool flag = 0;        for (int i = n - 2; i >= 1; --i) {            if (last) {                flag = 1;                break;            }            if (!Arr[i]) {                ++leftNum[i];                if (pos == -1) {                    pos = i + 1;                }                flag = 1;                ++rightNum[pos];                break;            }            else if (Arr[i]) {                ++leftNum[i];                if (pos == -1) {                    pos = i + 1;                }                ++rightNum[pos];            }        }        if (!flag) {            printf("NO\n");            continue;        }        else {            printf("YES\n");        }        for (int i = 1; i <= n; ++i) {            for (int j = 1; j <= leftNum[i]; ++j) {                printf("(");            }            printf("%d", Arr[i]);            for (int j = 1; j <= rightNum[i]; ++j) {                printf(")");            }            if (i < n) {                printf("->");            }        }        printf("\n");    }    return 0;}
2 0