Codeforces Round #644

Codeforces Round #644 (Div. 3)(2020.5.27)

今日新闻:零基础大哥经过半年ACM学习已经超过了大三学长,昨天一把Div2打上紫名。

我这个蒟蒻何时才能出头…

A、Minimal Square

这题只有两个矩形,所以肯定要么竖着并起来放要么横着并起来放,取个最小值就好了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    int t; cin >> t;
    while (t--)
    {
        int a, b; cin >> a >> b;
        ll ans = min(max(2 * a, b), max(a, 2 * b));
        cout << ans * ans << endl;
    }
    return 0;
}

B、Honest Coach

排个序,然后找相邻元素差最小的那个输出即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
int main()
{
    int t; cin >> t;
    while (t--)
    {
        int n; cin >> n;
        vector <int> a;
        for (int i = 1; i <= n; ++i)
        {
            int x; cin >> x;
            a.push_back(x);
            sort(a.begin(), a.end());
        }
        int ans = INF;
        for (int i = 1; i < a.size(); ++i)
            ans = min(ans, a[i] - a[i - 1]);
        cout << ans << endl;
    }
    return 0;
}

C、Similar Pairs

乍一看有些无从下手。

可以先统计一下奇偶性,如果都是偶数个那就可以两两配对。又因为题目给了 n n 是偶数,所以一个是奇数那另一个也必定是奇数,这时候可以取一奇一偶之后剩下的配对,然后我们就找一下有没有相差为1的数就可以了。因为相差为1时奇偶性必定不同。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    int t; cin >> t;
    while (t--)
    {
        int n; cin >> n;
        vector <int> a;
        int par[2] = {0};
        for (int i = 1; i <= n; ++i)
        {
            int x; cin >> x;
            a.push_back(x);
            par[x % 2]++;
        }
        if (par[0] % 2)
        {
            sort(a.begin(), a.end());
            for (int i = 1; i < a.size(); ++i)
                if (a[i] - a[i - 1] == 1)
                {
                    cout << "YES" << endl;
                    goto OUT_LOOP;
                }
            cout << "NO" << endl;
        }
        else cout << "YES" << endl;
        OUT_LOOP:;
    }
    return 0;
}

D、Buying Shovels

枚举最小袋数 i i ,看 n i n\over i 是否小于 k k

不过这样做还要当心枚举的 i i 一个都不满足 n i n\over i 小于 k k 的情况,此时并不一定 n n 就是最小值,所以可以在两种满足条件的情况中取个最小。

具体见代码。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
int main()
{
    int t; cin >> t;
    while (t--)
    {
        ll n, k; cin >> n >> k;
        ll ans = INF;
        for (ll i = 1; i * i <= n; ++i)
        {
            if (n % i == 0)
            {
                if (i <= k) ans = min(ans, n / i);
                if (n / i <= k) ans = min(ans, i);
            }
        }
        cout << ans << endl;
    }
    return 0;
}

E、Polygon

做题的时候看tag居然看到了什么最短路这种东西,吓死我了。

结果做完之后感觉这tag误导性真的很大。

先给判断条件:遍历整张图,对于1来说右边或者下面至少要有一个地方有1。

下面给出正确性证明:可以考虑一个类似于归纳法的东西。

最右边和最下面是边界,那么我们考虑与边界相邻的格子,这堆格子的任意一个01排列都是可以用某种顺序开炮得到的。

然后得到某个排列之后我们就可以把和边界相邻的格子删掉了,因为此时这些格子对答案没有影响。于是可以继续重复上述操作到所有格子全被删完为止。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 80;
int main()
{
    int t; cin >> t;
    while (t--)
    {
        int n; cin >> n;
        char mp[MAXN][MAXN];
        for (int i = 1; i <= n; ++i)
            cin >> mp[i] + 1;
        for (int i = 1; i <= n + 1; ++i) mp[n + 1][i] = '1';
        for (int i = 1; i <= n + 1; ++i) mp[i][n + 1] = '1';
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= n; ++j)
                if (mp[i][j] == '1')
                {
                    if (mp[i][j + 1] == '1' || mp[i + 1][j] == '1') continue;
                    else
                    {
                        cout << "NO" << endl;
                        goto OUT_LOOP;
                    }
                }
        cout << "YES" << endl;
        OUT_LOOP:;
    }
    return 0;
}

F、Spy-string

这种题果然是我的克星。

想了半天没想到什么好方法,看题解。

居然就是暴力中的暴力枚举哪一位修改,修改成什么。

好吧。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 50;
string a[MAXN];
bool check(int n, int k, string ans)
{
    for (int i = 1; i <= n; ++i)
    {
        int cnt = 0;
        for (int j = 0; j < k; ++j)
            if (ans[j] != a[i][j]) ++cnt;
        if (cnt > 1) return 0;
    }
    return 1;
}
int main()
{
    int t; cin >> t;
    while (t--)
    {
        int n, k; cin >> n >> k;
        for (int i = 1; i <= n; ++i) cin >> a[i];
        if (check(n, k, a[1])) cout << a[1] << endl;
        else
        {
            for (int i = 0; i < k; ++i)
            {
                map <char, int, less<int>> mp;
                for (int j = 1; j <= n; ++j) mp[a[j][i]]++;
                for (auto &j : mp)
                {
                    string ans = a[1];
                    ans[i] = j.first;
                    if (check(n, k, ans))
                    {
                        cout << ans << endl;
                        goto NEXT;
                    }
                }
            }
            cout << -1 << endl;
        }
        NEXT:;
    }
    return 0;
}

G、A/B Matrix

这题不太会构造,搞了半天还是错的。

于是请教队友,队友凭直觉一秒搞了个构造方法然后AC了…

我:???

首先存在与否的条件肯定是 a n = b m an=bm ,这没啥问题。

之后构造,队友说就从左往右构造。比如第一行就是第一个到第 a a 个元素全是1,之后的行在之前行的基础上继续往后写,第二行就从 a + 1 a+1 个元素开始写 a a 个1,如果跑到矩阵外面就回到第一个元素接着写。

不过我直接懵了。这为啥是对的?

后来简单想了一下发现真是对的。把这堆1排成一列,因为是按行写的所以个数肯定是 a n an 个。又由给出的存在条件,发现 a n = b m an=bm ,因此 a n an 也是 b b 的倍数,所以对于列来说1的位置就是个剩余系,肯定完全包含在里面了而且个数相等…

菜是原罪。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 100;
int main()
{
    int t; cin >> t;
    while (t--)
    {
        int n, m, a, b; cin >> n >> m >> a >> b;
        if (n * a != m * b)
        {
            cout << "NO" << endl;
            continue;
        }
        else
        {
            cout << "YES" << endl;
            bool matrix[MAXN][MAXN] ={0};
            int col = 1;
            for (int i = 1; i <= n; ++i)
                for (int j = 1; j <= a; ++j)
                {
                    matrix[i][col++] = 1;
                    if (col > m) col =1;
                }
            for (int i = 1; i <= n; ++i)
            {
                for (int j = 1; j <= m; ++j)
                    cout << matrix[i][j];
                cout << endl;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36000896/article/details/106393525