Codeforces #306 (div2)

A. Two Substrings
题意: 找这个串是否有不重复覆盖的AB和BA
思路: 用AB枚举BA 然后倒过来再做一次 或者找出AB和BA的位置 匹配一下
参考code:
当时逗了 - - 然后就fst了 虽然一改过了 代码比较丑
//
//  Created by TaoSama on 2015-06-05
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;

string s;

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(cin >> s) {
        int x = s.find("AB");
        int y = s.find("BA");
        bool ok = false;
        if(~x) {
            while(~y) {
                //cout << x << ' '<<y<<endl;
                if(abs(x - y) >= 2) {
                    ok = true;
                    break;
                }
                //cout<<y<<endl;
                y = s.find("BA", y + 1);
            }
        }
        if(ok) {
            puts("YES");
            continue;
        }

        x = s.find("BA");
        y = s.find("AB");
        ok = false;
        if(~x) {
            while(~y) {
                //cout << x << ' '<<y<<endl;
                if(abs(x - y) >= 2) {
                    ok = true;
                    break;
                }
                //cout<<y<<endl;
                y = s.find("AB", y + 1);
            }
        }
        puts(ok ? "YES" : "NO");
    }
    return 0;
}
B. Preparing Olympiad

题意: 选题 使得题目和在l和r直接 dif不超过x
思路: 直接dfs枚举或者二进制枚举
参考code:
二进制枚举
//
//  Created by TaoSama on 2015-06-05
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;

int n, l, r, x, a[15];

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(cin >> n >> l >> r >> x) {
        for(int i = 0; i < n; ++i) cin >> a[i];
        int ans = 0;
        for(int i = 0; i < 1 << n; ++i) {
            int Min = INF, Max = -INF, sum = 0;
            for(int j = 0; j < n; ++j) {
                if(i >> j & 1) {
                    Min = min(Min, a[j]);
                    Max = max(Max, a[j]);
                    sum += a[j];
                }
            }
            //cout<<endl;
            //cout << Max << ' ' << Min << ' ' << sum << endl;
            if(sum >= l && sum <= r && Max - Min >= x) ++ ans;
        }
        cout << ans << endl;
    }
    return 0;
}

C. Divisibility by Eight
题意: 求所给串的能被8整除的子序列
思路: 由于1000倍数一定能被8整除 所以只要枚举后三位就好了  n^3暴力 或者1000*n暴力都可以  当然cf题解还给了8*n的dp
参考code:
1000*n暴力
//
//  Created by TaoSama on 2015-06-05
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;

string s;
vector<int> G[10];

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);
    while(cin >> s) {
        for(int i = 0; i < 10; ++i) G[i].clear();
        for(int i = 0; i < s.size(); ++i)
            G[s[i] - '0'].push_back(i);
        bool ok = false;
        for(int i = 0; i < 1000; ++i) {
            if(i % 8 == 0) {
                int x = i;
                char b[5]; sprintf(b, "%d", x);
                int n = strlen(b), last = -1;
                int can = 0;
                for(int j = 0; j < n; ++j) {
                    for(int k = 0; k < G[b[j] - '0'].size(); ++k) {
                        if(G[b[j] - '0'][k] > last) {
                            ++can;
                            last = G[b[j] - '0'][k];
                            break;
                        }
                    }
                }
                if(can == n) {
                    ok = true, printf("YES\n%d\n", i);
                    break;
                }
            }
        }
        if(!ok) puts("NO");
    }
    return 0;
}

D. Regular Bridge
题意: 构造一个图 使得所有点的度为k 并且图里至少有一个桥
思路:   偶数度一定不行  删去那个桥 对于一个连通分量来说 有一个点度为奇数 其他都是偶数
这样的话这个连通分量就有奇数个奇度点 这违背了握手定理的推论 任何图(无向的或有向的)中,奇度顶点的个数是偶数。

对于奇度   先找两个点连成一个桥  并各自用一个点整出一个连通分量 
1 到 2, 3, ... , k - 1 这里有k-1度了  (1加上那个桥有k度了)
2, 3, ... , k - 1 互相连边构成一个 k - 2 度的完全图 加上上面的1度 有 k - 1度了
再找2个点 分别向 2, 3, ... , k - 1相连 使得 这两个点都有k-1度 它俩再连一条边 k度了
此时 2, 3, .... , k - 1 有 k+1度了   再把相邻边 2-3, 4-5, 6-7, k-2-k-1边删去  就都是k度了
另外一个连通分量同理
这样点数 就是V = 2k+4 由握手定理 E = V*k/2  特判一下k为1就好啦
参考code:
//
//  Created by TaoSama on 2015-06-05
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;

int k, con[300][300];

void addEdge(int s, int t) {
    for(int i = s; i <= t; ++i) {
        con[s - 1][i] = con[i][t + 1] = con[i][t + 2] = true;
        for(int j = i + 1; j <= t; ++j)
            con[i][j] = true;
    }

    for(int i = s; i < t; i += 2)  //decrease 1 degree
        con[i][i + 1] = false;

    con[t + 1][t + 2] = true;
}

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(cin >> k) {
        if(k % 2 == 0) {
            cout << "NO\n";
            continue;
        }
        cout << "YES\n";
        if(k == 1) {
            cout << "2 1\n2 1\n";
            continue;
        }

        memset(con, false, sizeof con);
        int V = 2 * k + 4, E = V * k >> 1;

        addEdge(2, k);
        con[1][k + 3] = true;
        addEdge(k + 4, V - 2);

        cout << V << ' ' << E << '\n';
        int cnt = 0;
        for(int i = 1; i <= V; ++i)
            for(int j = i + 1; j <= V; ++j)
                if(con[i][j]) cout << i << ' ' << j << '\n';
    }
    return 0;
}
E. Brackets in Implications
题意: 添加括号构造合法的式子 使得值为0 
思路:  这个人说的非常清楚了 我就不翻译了 @ RedNextYears
You must be clear fist on the fact that (x->1 = 1)
This means that the last number in the input must be zero.
So now our sequence takes the form "xxxxxx...0"
Now we want to make the second to last number equal to 1 in order to have (1->0 = 0)
Now we have two cases:
Case 1 "xxxxxx..10"
You can just leave the sequence as it is ... all the numbers to the left of the 1 will just have no effect .. and then the final value will be (1->0 = 0)
Case 2 "xxxxxx..00"
We need to turn this new 0 into a 1 somehow in order to be like case 1.
In order to get rid of this zero we have to match it with some other number.
From the rules, we have (1->0 = 0) and (0->0 = 1), so obviously we will try to match this 0 with another 0.
So we will search for the first 0 to the left of this 0.
So our sequence now takes the form "xxxx...0111..1100"
We can get rid of this group of 1s by grouping (1->1->1->1->....->0 = 0)
So now our sequence takes the form "xxxx...0(111..110)0" = "xxxx...000"
Now you will just have to group these two 0s together to change them into 1
"xxxx...(0(111..110))0" = "xxxx...(00)0" = "xxxx...10" = "0"
参考code:
//
//  Created by TaoSama on 2015-06-06
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;

int n, a[N];

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(cin >> n) {
        for(int i = 1; i <= n; ++i) cin >> a[i];
        if(a[n] == 1) {
            cout << "NO\n";
            continue;
        }
        bool ok = false;
        if(n == 1 && a[1] == 0) {
            cout << "YES\n0\n";
            continue;
        }
        if(n >= 2 && a[n - 1] == 1 && a[n] == 0)  {
            cout << "YES\n";
            for(int i = 1; i <= n; ++i)
                cout << a[i] << (i == n ? "" : "->");
            cout << "\n";
            continue;
        }
        string cur;  //"xxxx...(0(111..110))0" = "xxxx...(00)0" = "xxxx...10" = "0"
        for(int i = 1; i <= n - 2; ++i) {
            if(a[i]) cur += (a[i] + '0'), cur += "->";
            else {
                ok = true;
                cout << "YES\n";
                cout << cur << "(0->";  //已经把当前位置打印了
                bool have = ++i <= n - 2;  //如果还有
                if(have) cout << "(";  //插一个括号
                while(i <= n - 2) cout << a[i++] << "->";
                cout << "0)";  //打印倒数第二个0
                if(have) cout << ")";
                cout << "->0\n";  //最后那个0
            }
        }
        if(!ok) cout << "NO\n";
    }
    return 0;
}


你可能感兴趣的:(构造)