Codeforces Round #306 (Div. 2)

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值