Codeforces Round #632 (Div. 2)

A. Little Artem

题意

有一 $n{ imes}m$ 网格,输出一种使得 与白色相邻的黑色格数 = 与黑色相邻的白色格数 $+ 1$ 的染色方案。

思路

一角染白。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n, m; cin >> n >> m;
    char mp[n][m];
    fill(*mp, *mp + n * m, 'B');
    mp[0][0] = 'W';
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            cout << mp[i][j] ;
        }
        cout << "
";
    }
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

B. Kind Anton

题意

数组 $a$ 由 ${-1,0,1}$ 组成,可以使 $a_i$ 加上左侧 $a_j$ 任意次,问数组 $a$ $b$ 能否相等。

思路

判断每个与 $b_i$ 不等的 $a_i$ 左侧是否有满足条件的 $a_j$,即记录最左侧的 $-1 / 1$ 。

代码

#include <bits/stdc++.h>
using namespace std;

void solve() {
    int n; cin >> n;
    int a[n]; for(int & i : a) cin>>i;
    int b[n]; for(int & i : b) cin>>i;
    int l_1 = find(a, a + n, -1) - a;
    int l1 = find(a, a + n, 1) - a;
    for (int i = 0; i < n; i++) {
        if ((b[i] > a[i] && l1 >= i) || (b[i] < a[i] && l_1 >= i)) {
            cout << "NO" << "
";
            return;
        }
    }
    cout << "YES" << "
";
}

int main() {
    int t; cin >> t;
    while (t--) solve();
}

C. Eugene and an array

题意

统计数组 $a$ 中有多少连续子序列,其本身及其连续子序列的和均不为 $0$ 。

思路

将数组从 $[0,n-1]$ 编号,若存在一和为 $0$ 的连续子序列 $[i,j]$,则 $pre\_sum[i-1] = pre\_sum[j]$,此 $0$ 序列与之前的 $i$ 个数共构成 $i+1$ 个 $0$ 序列,将之后的每个数接在 $0$ 序列的末尾也都会再构成 $i+1$ 个 $0$ 序列,若之后仍有 $0$ 序列,更新已知 $0$ 序列的最大长度后就又变成了和之前一样的情况。

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
map<ll, ll> MP;
int main() {
    int n; cin >> n;
    int a[n]; for (int & i : a) cin >> i;
    MP[0] = 0;
    ll r = -1, sum = 0, ans = (n + 1LL) * n / 2;
    for (int i = 0; i < n; i++) {
        sum += a[i];
        if (MP.count(sum)) r = max(r, MP[sum]);
        ans -= r + 1;
        MP[sum] = i + 1;
    }
    cout << ans;
}

D. Challenges in school №41

题意

输出用 $k$ 轮将字符串中所有的 $RL$ 翻转成 $LR$ 的任一方案。

思路

$min_k$ = 每轮翻转串中所有已存在 $RL$ 需要的轮数,$max_k$ = 每轮翻转一个 $RL$ 需要的轮数,如果 $k$ 位于二者之间则一定有解,当 $k=min_k$ 时逐轮输出即可,当 $k>min_k$ 时需要将一些轮分解输出直至 $k = min_k - used_k$ 。

代码

#include <bits/stdc++.h>
using namespace std;

const int MAX_N = 3030;

vector<int> v[MAX_N];
int n, k, min_k, max_k;
char s[MAX_N];

int main() {
    cin >> n >> k >> (s + 1);
    while (1) {
        bool flag = true;
        for (int i = 1; i <= n; i++) {
            if (s[i] == 'R' && s[i + 1] == 'L') {                
                v[min_k].push_back(i);
                flag = false;
            }
        }
        for (int i : v[min_k]) swap(s[i], s[i + 1]);
        max_k += v[min_k].size();
        if (flag) break;
        ++min_k;
    }
    if (k < min_k || k > max_k) {
        cout << "-1";
        return 0;
    }
    for (int i = 0; i < min_k; i++) {
        while (!v[i].empty() && k > min_k - i) {
            cout << "1 " << v[i].back() << "
";
            v[i].pop_back();
            --k;
        }
        if (!v[i].empty()) {
            cout << v[i].size();
            for (int j : v[i]) cout << ' ' << j;
            cout << "
";
            --k;
        }
    }
}

F. Kate and imperfection

题意

有一集合 $S={1,2,3,...,n}$,构造大小为 $k(1<k≤n)$ 的集合,使得两两数间 $gcd$ 的最大值最小并输出该最小值。

思路

       我们考虑如何构造两两间最大公因数的最大值最小的集合,首先肯定是把所有质数先丢进集合里,然后再把与已经在集合内的数的最大公因数 =2 的数丢进去,然后是 =3 的数……然后注意到,如果我们加入了一个合数,那么他的所有因子必定已经在集合内了,于是加入的这个数字能够产生的最大公因数就是他的最大因子,因此用埃筛维护这个贪心的过程,排序一遍输出即可。——st1vdy

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n; cin >> n;
    vector<int> ans(n + 1, 1);
    for (int i = 2; i <= n; i++) {
        for (int j = i + i; j <= n; j += i) {
            ans[j] = i;
        }
    }    
    sort(ans.begin(), ans.end());
    for (int i = 2; i <= n; i++) cout << ans[i] << ' ';
}

参考了: st1vdy 的博客。

原文地址:https://www.cnblogs.com/Kanoon/p/12664168.html