Educational Codeforces Round 70 题解

比赛链接https://codeforc.es/contest/1202
 
A. You Are Given Two Binary Strings...
题意:给出两个二进制数\(f(x)\)\(f(y)\),定义一个二进制数\(s_k=f(x)+2^k\cdot f(y)\),询问\(k\)取何值时\(s_k\)的反向字符串(将二进制数看作01串)字典序最小。

分析:首先,我们需要知道对于一个二进制数乘2,相当于将该数整体左移一位,因此我们只需要找到\(f(y)\)最右侧的1的位置\(pos\),令它去和\(f(x)\)\(pos\)左侧最近的\(y\)匹配,这样得到的反向字符串字典序必然最小。

AC代码

#include <bits/stdc++.h>
#define SIZE 200007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
typedef long long ll;
void io() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
}
ll n, m, t;
string s1, s2;
int main() {
    io(); cin >> t;
    while(t--) {
        cin >> s1 >> s2;
        int len1 = s1.length() - 1, len2 = s2.length() - 1;
        n = 0;
        while(s2[len2--] == '0') ++n;
        m = n;
        while(s1[len1 - m] == '0') ++m;
        cout << m - n << endl;
    }
}

 
B. You Are Given a Decimal String...
题意:不是很讲得清楚,可以看题中样例理解。给出一个字符串字符串中的每一位数字由确定的两个数字任意组合得到,询问,为了得到该字符串,最少需要多构成几个无效数字。例如:
给出字符串\(0840\),确定的两个数字为\((2, 4)\)

  1. 0 (初始必定为零)
  2. 04 (\(+4\)
  3. 048 (\(+4\)
  4. 0482 (\(+4\),如果超过10就只取个位数)
  5. 04824 (\(+2\)
  6. 048248 (\(+4\)
  7. 0482480 (\(+2\)

于是,(0) 4 (8) 2 (4) 8 (0),多生成的数的个数为3。

分析:从字符串第\(k\)位到\(k+1\)位实际上相当于变化了\(\vert s_{k+1}-s_k \vert\),这个值不会超过10,因此我们只需要暴力求出这10种情况所生成的无效数字个数即可。

AC代码

#include <bits/stdc++.h>
#define SIZE 200007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
const int maxn = 1e9;
using namespace std;
typedef long long ll;
void io() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
}
int n, m, t; int dp[10];
string s;
int main() {
    io(); cin >> s;
    int len = s.length();
    rep(i, 0, 9) {
        rep(j, 0, 9) {
            rep(i, 0, 9) dp[i] = maxn;
            rep(x, 0, 9) {
                rep(y, 0, 9) {
                    if (!x && !y) continue;
                    dp[(x * i + y * j) % 10] = min(x + y - 1, dp[(x * i + y * j) % 10]);
                }
            }
            int ans = 0;
            rep(k, 0, len - 2) {
                int tmp = s[k + 1] - s[k];
                if (dp[(tmp + 10) % 10] == maxn) { ans = -1; break; }
                ans += dp[(tmp + 10) % 10];
            }
            cout << ans << ' ';
        }
        cout << endl;
    }
}

 
C. You Are Given a WASD-string...
题意:T组输入,每组输入给出一个只含“\(W, A, S, D\)”的字符串(又是字符串...)。\(W, A, S, D\)分别代表一个机器人可以向上,左,下,右四个方向移动一格。定义机器人走过的面积为能包含所有机器人走到过的格子的最小面积。现在,你能在字符串中的任意位置加入一个字符(只能为\(W, A, S, D\)),询问可能的机器人走过的最小面积。

分析:由于只能加入一个字符,所以我们发现横向的移动和纵向移动互不干扰(最小矩形只能是长或者宽缩进一个单位),因此我们只需要分成横向纵向两个子问题考虑,并找到最小面积即可。我用了一种前缀和的思想写,而标程给出了更简洁的解法。

AC代码

#include <bits/stdc++.h>
#define SIZE 200007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
void io() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
}
int n, m, t;
string str;
struct node {
    int val;
    int pos;
    int la, lb, ra, rb;
}p1[SIZE], p2[SIZE];
void init1(node p[], int n) {
    int x = INF, y = -INF;
    rep(i, 0, n) {
        p[i].la = min(x, p[i].pos);
        x = min(x, p[i].la);
        p[i].ra = max(y, p[i].pos);
        y = max(y, p[i].ra);
    }
}
void init2(node p[], int n) {
    int x = INF, y = -INF;
    for (int i = n; i >= 0; --i) {
        p[i].lb = min(x, p[i].pos);
        x = min(x, p[i].lb);
        p[i].rb = max(y, p[i].pos);
        y = max(y, p[i].rb);
    }
}
int main() {
    io(); cin >> t;
    while (t--) {
        cin >> str;
        int k = 1, j = 1;
        rep(i, 0, str.length() - 1) {
            if (str[i] == 'W') p1[k++].val = 1;
            else if (str[i] == 'S') p1[k++].val = -1;
            else if (str[i] == 'A') p2[j++].val = 1;
            else p2[j++].val = -1;
        }
        rep(i, 0, k - 1) p1[i].pos = p1[i - 1].pos + p1[i].val;
        rep(i, 0, j - 1) p2[i].pos = p2[i - 1].pos + p2[i].val;
        init1(p1, k - 1); init1(p2, j - 1);
        init2(p1, k - 1); init2(p2, j - 1);
        ll w = p1[k - 1].ra, a = p2[j - 1].la, s = p1[k - 1].la, d = p2[j - 1].ra;
        ll h = p1[k - 1].ra - p1[k - 1].la + 1, wid = p2[j - 1].ra - p2[j - 1].la + 1;
        bool f1 = false, f2 = false;
        rep(i, 0, k - 1) {
            if (p1[i].lb < p1[i].la && p1[i].rb < p1[i].ra) { f1 = true; break; }
            if (p1[i].lb > p1[i].la && p1[i].rb > p1[i].ra) { f1 = true; break; }
        }
        rep(i, 0, j - 1) {
            if (p2[i].lb < p2[i].la && p2[i].rb < p2[i].ra) { f2 = true; break; }
            if (p2[i].lb > p2[i].la && p2[i].rb > p2[i].ra) { f2 = true; break; }
        }
        if (f1 || f2) {
            if (f1 && f2) {
                if (wid > h) cout << wid * (h - 1) << endl;
                else cout << (wid - 1) * h << endl;
                continue;
            }
            if (f1) cout << wid * (h - 1) << endl;
            else cout << (wid - 1) * h << endl;
        }
        else cout << wid * h << endl;
    }
}

 
D. Print a 1337-string...
题意:给出一个正整数\(n\),构造一个含有\(n\)\(1337\)子串的字符串(还是字符串...)。

分析:我们考虑每次构造\(C_n^2\)个直到完成例如 \(10=6+3+1\),那么我们就能构造出\(13373737\)。但要注意最后可能会剩下2,可是不能重复构造两次1。因此最后为2的构造我们在倒数第三位插入两个1,例如:\(8=6+2\) 构造出:\(13311337\)

AC代码

#include <bits/stdc++.h>
#define SIZE 200007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
typedef long long ll;
void io() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
}
ll n, m, t; bool flag;
ll dp[SIZE];
vector<int> v;
int main() {
    io(); cin >> t;
    rep(i, 1, 100050) dp[i] = 1ll * i * (i - 1) / 2;
    while (t--) {
        cin >> n; m = n; v.clear();
        if (n == 2) { cout << "11337\n"; continue; }
        flag = false;
        while (n) {
            int pos = lower_bound(dp, dp + 100010, n) - dp;
            if (dp[pos] > n) --pos;
            n -= dp[pos];
            v.emplace_back(pos);
            if (n == 2) { flag = true; break; }
        }
        int cnt = 1, it = v.size() - 1;
        cout << "13";
        while (cnt < v[0]) {
            if (flag && cnt == v[0] - 2) cout << "11";
            if (cnt < v[it]) cout << 3;
            else { --it, --cnt; cout << 7; }
            cnt++;
        }
        cout << "7\n";
    }
}

猜你喜欢

转载自www.cnblogs.com/st1vdy/p/11329097.html